Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

3D graphics programming in Java, Part 1: Java 3D

Get a head start with this introduction to the Java 3D API

  • Print
  • Feedback

Page 4 of 5

There's no magic in how the public and private Java 3D classes interface with system resources, either. Sun installs native libraries in J3D.dll and j3daudio.dll under the /jre/bin/ directory. The Java 3D classes use native methods to call these DLLs and interface with the Win32 platform and OpenGL rendering library. (Similar libraries exist for Solaris implementations.)

One final note on installation: The OpenGL rendering pipeline is designed to take advantage of OpenGL acceleration hardware to speed up your graphics applications. For the purposes of this column, though, you should be able to experiment with the examples without any special hardware. (In fact, I'm developing all the examples on a Pentium 150-MHz MMX laptop with no OpenGL acceleration hardware.) If you're interested in acceleration cards, you should refer to the OpenGL Web site or the Java 3D mailing list (see Resources) for more information. I plan to include a little more information in next month's Java 3D column on acceleration hardware, too.

Constructing the view branch of the scene

As I noted earlier, one of the biggest strengths of the scene graph graphics model is that it allows inexperienced graphics programmers to add 3D to their applications. Traditionally, 3D programmers have had to specify where and how individual lines or other graphics primitives are to be drawn. Using a scene graph, however, the programmer simply creates a tree-like structure containing nodes that represent objects to be rendered as well as rendering instructions (such as where the viewpoint displayed to the monitor is located, physical geometry of the 3D world the programmer is creating, and relative distances between things).

In Java 3D, there are two major portions, or branches, to this tree: the view branch and the content branch. The content branch contains nodes describing the actual objects you want to render, including how to draw them, how to color them, textures to place on the primitives, how the objects are arranged in space, and how the objects should behave interactively. The view branch contains everything else, but in practice this branch is actually quite small compared to the content branch. View branches will often contain only a few nodes, while content branches may contain thousands for complicated 3D worlds.

Example 1 provides a simple example for creating a Java 3D scene graph. We see how to use the heavyweight Canvas3D component within a Frame container, how to create the view branch of the graph, and how to attach a View to it. The content branch portion is left empty, so that we render an empty universe.

001 //Comment out the following package statement to compile separately.
002 package com.javaworld.media.j3d;
003 
004 import java.awt.*;
005 import java.awt.event.*;
006 import javax.media.j3d.*;
007 
008 public class Example01 extends Frame {
009   /**
010    * Instantiates an Example01 object.
011   **/
012   public static void main(String args[]) {
013     new Example01();
014   }
015 
016   /**
017    * The Example01 constructor sets the frame's size, adds the
018    * visual components, and then makes them visible to the user.
019    *
020    * We place a Canvas3D object into the Frame so that Java 3D
021    * has the heavyweight component it needs to render 3D
022    * graphics into.  We then call methods to construct the
023    * View and Content branches of our scene graph.
024   **/
025   public Example01() {
026     //Title our frame and set its size.
027     super("Java 3D Example01");
028     setSize(400,300); 
029 
030     //Here is our first Java 3D-specific code.  We add a
031     //Canvas3D to our Frame so that we can render our 3D
032     //graphics.  Java 3D requires a heavyweight component
033     //Canvas3D into which to render.
034     Canvas3D myCanvas3D = new Canvas3D(null);
035     add("Center",myCanvas3D);
036 
037     //Turn on the visibility of our frame.
038     setVisible(true);
039 
040     //We want to be sure we properly dispose of resources 
041     //this frame is using when the window is closed.  We use 
042     //an anonymous inner class adapter for this.
043     addWindowListener(new WindowAdapter() 
044       {public void windowClosing(WindowEvent e) 
045          {dispose(); System.exit(0);}  
046       }
047     );
048 
049     //Now that we have our Frame and Canvas3D, we are ready
050     //to start building our scene graph.  We need to construct
051     //both a view branch and a content branch.  In order to
052     //actually use our view branch, we also need to construct
053     //a View and connect it to our view branch's ViewPlatform.
054     View myView = constructView(myCanvas3D);
055     Locale myLocale = constructViewBranch(myView);
056     constructContentBranch(myLocale);
057   }
058 
059   /**
060    * constructView() takes a Canvas3D reference and constructs
061    * a View to display in that Canvas3D.  It uses the default
062    * PhysicalBody and PhysicalEnvironment (both required to be
063    * set or else the 3D runtime will throw exceptions).  The
064    * returned View is used by constructViewBranch() to attach
065    * the scene graph's ViewPlatform to a Canvas3D for rendering.
066    *
067    * @see constructViewBranch(View)
068   **/
069   private View constructView(Canvas3D myCanvas3D) {
070     View myView = new View();
071     myView.addCanvas3D(myCanvas3D);
072     myView.setPhysicalBody(new PhysicalBody());
073     myView.setPhysicalEnvironment(new PhysicalEnvironment());
074     return(myView);
075   }
076 
077 
078   /**
079    * constructViewBranch() takes as input a View which we
080    * attached to our Canvas3D in constructView().  It constructs
081    * a default view branch for the scene graph, attaches
082    * the View to the ViewPlatform, and returns a reference to
083    * our Locale for use by constructContentBranch()
084    * in creating content for our scene graph.
085    *
086    * @see constructView(Canvas3D)
087    * @see constructContentBranch(Locale)
088   **/
089   private Locale constructViewBranch(View myView) {
090 
091     //First, we create the necessary coordinate systems 
092     //(VirtualUniverse, Locale), container nodes
093     //(BranchGroup, TransformGroup), and platform which 
094     //determines our viewing position and direction (ViewPlatform).  
095     VirtualUniverse myUniverse = new VirtualUniverse();
096     Locale myLocale = new Locale(myUniverse);
097     BranchGroup myBranchGroup = new BranchGroup();
098     TransformGroup myTransformGroup = new TransformGroup();
099     ViewPlatform myViewPlatform = new ViewPlatform();
100 
101     //Next, we insert the platform into the transform group, 
102     //the transform group into the branch group, and the branch
103     //group into the locale's branch graph portion of the 
104     //scene graph.
105     myTransformGroup.addChild(myViewPlatform);
106     myBranchGroup.addChild(myTransformGroup);
107     myLocale.addBranchGraph(myBranchGroup);
108 
109     //Finally, we attach our view to the view platform and we
110     //return a reference to our new universe.  We are ready to 
111     //render 3D content!
112     myView.attachViewPlatform(myViewPlatform);
113     return(myLocale);
114   }
115 
116   /**
117    * constructContentBranch() is where we specify the 3D graphics
118    * content to be rendered into the Locale referenced
119    * in the passed parameter.  Nothing is currently specified, so we
120    * render an empty universe.
121    *
122    * @see constructViewBranch(View)
123   **/
124   private void constructContentBranch(Locale myLocale) {
125     //Insert content to be rendered here.
126   }
127 }


How lonely it is in an empty universe

Placing content into the Java 3D scene graph

Now, let's provide some content to be rendered. We'll start with static content: Next month, we'll add behaviors (interactivity).

One interesting thing to note about Java 3D is that it does not provide primitives like spheres or cubes. The designers of the API chose to instead provide robust support for things like GeometryArrays, so that developers could build up graphics primitives while allowing the Java 3D runtime to optimize as much as possible for speed. The astute observer will note when we get to our OpenGL discussion a couple of month's hence that the primitives provided in Java 3D closely map to those provided in OpenGL, no surprise considering the layering of Java 3D on top of OpenGL.

One result of this design decision is that you will either have to spend a lot of time creating primitives over and over again, or you will need to use a primitive library built for Java 3D.

For Example 2, we sidestep the issue by rendering a three dimensional text string. Java 3D builds on top of the new text support provided in Java 2D (see the listing of my previous columns in the Resources for more information on Java 2D and text).

Using the 3D text support, our updated constructViewBranch() method is:

001   /**
002    * constructContentBranch() is where we specify the 3D graphics
003    * content to be rendered into the VirtualUniverse referenced
004    * in the passed parameter.  As an example, let's render a
005    * some three dimensional text:  We render the word "JavaWorld"
006    * in Times Roman font, extruded, then translated, scaled, and
007    * rotated off of the original coordinate axes.
008    *
009    * Compare to Java 2D example com.javaworld.media.j2d.Example04: 
010    * http://www.javaworld.com/javaworld/jw-07-1998/jw-07-media.html 
011    *
012    * @see constructViewBranch(View)
013   **/
014   private void constructContentBranch(Locale myLocale) {
015     //We first create a regular 2D font, then from that a
016     //3D font, 3D text, and 3D shape, in succession.  We use
017     //the default constructors for FontExtrusion and Appearance.
018     Font myFont = new Font("TimesRoman",Font.PLAIN,10);
019     Font3D myFont3D = new Font3D(myFont,new FontExtrusion());
020     Text3D myText3D = new Text3D(myFont3D, "JavaWorld");
021     Shape3D myShape3D = new Shape3D(myText3D, new Appearance());   
022 
023     //We created a new branch group and transform group to hold
024     //our content.  This time when we create the transform group,
025     //however, we pass in a Transform3D to the transform group's
026     //constructor.  This 3D transform has been manipulated
027     //to perform the transformations we desire, which results
028     //in those manipulations being carried out on all children
029     //of the given transform group, in this case, our content.
030     BranchGroup contentBranchGroup = new BranchGroup();
031     Transform3D myTransform3D = new Transform3D();
032     myTransform3D.setTranslation(new Vector3f(-1.0f,0.0f,-4.0f));
033     myTransform3D.setScale(0.1);
034     Transform3D tempTransform3D = new Transform3D();
035     tempTransform3D.rotY(Math.PI/4.0d);
036     myTransform3D.mul(tempTransform3D);
037     TransformGroup contentTransformGroup = new TransformGroup(myTransform3D);
038 
039     //We add our child nodes and insert the branch group into
040     //the live scene graph.  This results in Java 3D rendering
041     //the content.
042     contentTransformGroup.addChild(myShape3D);
043     contentBranchGroup.addChild(contentTransformGroup);
044     myLocale.addBranchGraph(contentBranchGroup);
045   }


Our universe is empty no more!

  • Print
  • Feedback

Resources
  • A good place to start is the Introduction to Programming with Java 3D course tutorial put together by Sun and the San Diego Supercomputer Center. http://www.sdsc.edu/~nadeau/Courses/SDSCjava3d/
  • Sun's Java 3D API page documents the API and its use. It contains javadocs for the API, the mailing list archive, Sun's Java 3D FAQ, and more. http://java.sun.com/products/java-media/3D/
  • The API is specified in Sun's Java 3D API Specification document. http://java.sun.com/products/java-media/3D/forDevelopers/j3dguide/j3dTOC.doc.html
  • The specification is also available in book format from Addison-Wesley's Java Series. Please note that the version of the API this printed specification corresponds to may be somewhat out of date The online specification is always kept up to date for the latest API release. http://www.amazon.com/exec/obidos/ASIN/0201325764/billday/
  • Sun makes its Win32 and Solaris implementations (as opposed to the API specification itself) available from a separate, product Web site. This site also contains the example code for Sun Java 3D training courses, demos from the Java 3D programming contest Sun hosted earlier in 1998, case studies with Sun's Java 3D customers, and lists of Java 3D related papers and Web pages. http://www.sun.com/desktop/java3d/index.html
  • Sun's Java 3D product site links to the course notes for its "Java 3D Roadshow." This is the crash course Sun representatives have been teaching to interested developers around the world in 1998. http://www.sun.com/desktop/java3d/collateral/j3d_clas.pdf
  • The OpenGL Consortium's Web site is the complete resource for OpenGL. http://www.opengl.org/
  • The Java 3D FAQ is maintained by Steve Pietrowicz, a project manager of the Java 3D group at NCSA. It is an excellent third-party resource for Java 3D information. http://tintoy.ncsa.uiuc.edu/~srp/java3d/faq.html
  • Read more about Java 3D's heavyweight components and Sun's thoughts on integrating them with Swing lightweight components. http://java.sun.com/products/java-media/mail-archive/3D/1520.html
  • Follow-up on Sun's plans for Java 3D vis-a-vis lightweight components and Swing. http://java.sun.com/products/java-media/mail-archive/3D/1557.html
  • "Progress on the media front at Siggraph '98" sizes up the state of Java Media in general and Java 3D in particular at this year's premier computer graphics conference. http://www.javaworld.com/javaworld/jw-10-1998/jw-10-media.html
  • Download source code and classes for this column. http://www.javaworld.com/jw-12-1998/media/jw-12-media.jar
  • Bill has archived Media Programming resources on his Web site. This archive contains the up-to-date media.jar file with code fixes for all of the examples in the column. http://reality.sgi.com/bday/Work/index.html
  • Read Bill's previous Media Programming columns. http://www.javaworld.com/topicalindex/jw-ti-media.html