Java 3D Concepts

The Java 3D API specification serves to define objects, methods, and their actions precisely. Describing how to use an API belongs in a tutorial or programmer's reference manual, and is well beyond the scope of this specification. However, a short introduction to the main concepts in Java 3D will provide the context for understanding the detailed, but isolated, specification found in the class and method descriptions. We introduce some of the key Java 3D concepts and illustrate them with some simple program fragments.

Basic Scene Graph Concepts

A scene graph is a "tree" structure that contains data arranged in a hierarchical manner. The scene graph consists of parent nodes, child nodes, and data objects. The parent nodes, called Group nodes, organize and, in some cases, control how Java 3D interprets their descendants. Group nodes serve as the glue that holds a scene graph together. Child nodes can be either Group nodes or Leaf nodes. Leaf nodes have no children. They encode the core semantic elements of a scene graph- for example, what to draw (geometry), what to play (audio), how to illuminate objects (lights), or what code to execute (behaviors). Leaf nodes refer to data objects, called NodeComponent objects. NodeComponent objects are not scene graph nodes, but they contain the data that Leaf nodes require, such as the geometry to draw or the sound sample to play.

A Java 3D application builds and manipulates a scene graph by constructing Java 3D objects and then later modifying those objects by using their methods. A Java 3D program first constructs a scene graph, then, once built, hands that scene graph to Java 3D for processing.

The structure of a scene graph determines the relationships among the objects in the graph and determines which objects a programmer can manipulate as a single entity. Group nodes provide a single point for handling or manipulating all the nodes beneath it. A programmer can tune a scene graph appropriately by thinking about what manipulations an application will need to perform. He or she can make a particular manipulation easy or difficult by grouping or regrouping nodes in various ways.

Constructing a Simple Scene Graph

The following code constructs a simple scene graph consisting of a group node and two leaf nodes.

Listing 1 – Code for Constructing a Simple Scene Graph


Shape3D myShape1 = new Shape3D(myGeometry1, myAppearance1);
Shape3D myShape2 = new Shape3D(myGeometry2);
myShape2.setAppearance(myAppearance2);

Group myGroup = new Group();
myGroup.addChild(myShape1);
myGroup.addChild(myShape2);

It first constructs one leaf node, the first of two Shape3D nodes, using a constructor that takes both a Geometry and an Appearance NodeComponent object. It then constructs the second Shape3D node, with only a Geometry object. Next, since the second Shape3D node was created without an Appearance object, it supplies the missing Appearance object using the Shape3D node's setAppearance method. At this point both leaf nodes have been fully constructed. The code next constructs a group node to hold the two leaf nodes. It uses the Group node's addChild method to add the two leaf nodes as children to the group node, finishing the construction of the scene graph. Figure 1 shows the constructed scene graph, all the nodes, the node component objects, and the variables used in constructing the scene graph.

A Simple Scene Graph

A Place For Scene Graphs

Once a scene graph has been constructed, the question becomes what to do with it? Java 3D cannot start rendering a scene graph until a program "gives" it the scene graph. The program does this by inserting the scene graph into the virtual universe.

Java 3D places restrictions on how a program can insert a scene graph into a universe.

A Java 3D environment consists of two superstructure objects, VirtualUniverse and Locale, and one or more graphs, rooted by a special BranchGroup node. Figure 2 shows these objects in context with other scene graph objects.

The VirtualUniverse object defines a universe. A universe allows a Java 3D program to create a separate and distinct arena for defining objects and their relationships to one another. Typically, Java 3D programs have only one VirtualUniverse object. Programs that have more than one VirtualUniverse may share NodeComponent objects but not scene graph node objects.

The Locale object specifies a fixed position within the universe. That fixed position defines an origin for all scene graph nodes beneath it. The Locale object allows a programmer to specify that origin very precisely and with very high dynamic range. A Locale can accurately specify a location anywhere in the known physical universe and at the precision of Plank's distance. Typically, Java 3D programs have only one Locale object with a default origin of (0, 0, 0). Programs that have more than one Locale object will set the location of the individual Locale objects so that they provide an appropriate local origin for the nodes beneath them. For example, to model the Mars landing, a programmer might create one Locale object with an origin at Cape Canaveral and another with an origin located at the landing site on Mars.

Content Branch, View Branch, Superstructure

The BranchGroup node serves as the root of a branch graph. Collectively, the BranchGroup node and all of its children form the branch graph. The two kinds of branch graphs are called content branches and view branches. A content branch contains only content-related leaf nodes, while a view branch contains a ViewPlatform leaf node and may contain other content-related leaf nodes. Typically, a universe contains more than one branch graph-one view branch, and any number of content branches.

Besides serving as the root of a branch graph, the BranchGroup node has two special properties: It alone may be inserted into a Locale object, and it may be compiled. Java 3D treats uncompiled and compiled branch graphs identically, though compiled branch graphs will typically render more efficiently.

We could not insert the scene graph created by our simple example (Listing 1) into a Locale because it does not have a BranchGoup node for its root. Listing 2 shows a modified version of our first code example that creates a simple content branch graph and the minimum of superstructure objects. Of special note, Locales do not have children, and they are not part of the scene graph. The method for inserting a branch graph is addBranchGraph, whereas addChild is the method for adding children to all group nodes.

Listing 2 – Code for Constructing a Scene Graph and Some Superstructure Objects


Shape3D myShape1 = new Shape3D(myGeometry1, myAppearance1);
Shape3D myShape2 = new Shape3D(myGeometry2, myAppearance2);

BranchGroup myBranch = new BranchGroup();
myBranch.addChild(myShape1);
myBranch.addChild(myShape2);
myBranch.compile();

VirtualUniverse myUniverse = new VirtualUniverse();
Locale myLocale = new Locale(myUniverse);
myLocale.addBranchGraph(myBranch);

SimpleUniverse Utility

Most Java 3D programs build an identical set of superstructure and view branch objects, so the Java 3D utility packages provide a universe package for constructing and manipulating the objects in a view branch. The classes in the universe package provide a quick means for building a single view (single window) application. Listing 3 shows a code fragment for using the SimpleUniverse class. Note that the SimpleUniverse constructor takes a Canvas3D as an argument, in this case referred to by the variable myCanvas.

Listing 3 – Code for Constructing a Scene Graph Using the Universe Package


import com.sun.j3d.utils.universe.*;

Shape3D myShape1 = new Shape3D(myGeometry1, myAppearance1);
Shape3D myShape2 = new Shape3D(myGeometry2, myAppearance2);

BranchGroup myBranch = new BranchGroup();
myBranch.addChild(myShape1);
myBranch.addChild(myShape2);
myBranch.compile();

SimpleUniverse myUniv = new SimpleUniverse(myCanvas);
myUniv.addBranchGraph(myBranch);

Processing a Scene Graph

When given a scene graph, Java 3D processes that scene graph as efficiently as possible. How a Java 3D implementation processes a scene graph can vary, as long as the implementation conforms to the semantics of the API. In general, a Java 3D implementation will render all visible objects, play all enabled sounds, execute all triggered behaviors, process any identified input devices, and check for and generate appropriate collision events.

The order that a particular Java 3D implementation renders objects onto the display is carefully not defined. One implementation might render the first Shape3D object and then the second. Another might first render the second Shape3D node before it renders the first one. Yet another implementation may render both Shape3D nodes in parallel.

Features of Java 3D

Java 3D allows a programmer to specify a broad range of information. It allows control over the shape of objects, their color, and transparency. It allows control over background effects, lighting, and environmental effects such as fog. It allows control over the placement of all objects (even nonvisible objects such as lights and behaviors) in the scene graph and over their orientation and scale. It allows control over how those objects move, rotate, stretch, shrink, or morph over time. It allows control over what code should execute, what sounds should play, and how they should sound and change over time.

Java 3D provides different techniques for controlling the effect of various features. Some techniques act fairly locally, such as getting the color of a vertex. Other techniques have broader influence, such as changing the color or appearance of an entire object. Still other techniques apply to a broad number of objects. In the first two cases, the programmer can modify a particular object or an object associated with the affected object. In the latter case, Java 3D provides a means for specifying more than one object spatially.

Bounds

Bounds objects allow a programmer to define a volume in space. There are three ways to specify this volume: as a box, a sphere, or a set of planes enclosing a space.

Bounds objects specify a volume in which particular operations apply. Environmental effects such as lighting, fog, alternate appearance, and model clipping planes use bounds objects to specify their region of influence. Any object that falls within the space defined by the bounds object has the particular environmental effect applied. The proper use of bounds objects can ensure that these environmental effects are applied only to those objects in a particular volume, such as a light applying only to the objects within a single room.

Bounds objects are also used to specify a region of action. Behaviors and sounds execute or play only if they are close enough to the viewer. The use of behavior and sound bounds objects allows Java 3D to cull away those behaviors and sounds that are too far away to affect the viewer (listener). By using bounds properly, a programmer can ensure that only the relevant behaviors and sounds execute or play.

Finally, bounds objects are used to specify a region of application for per-view operations such as background, clip, and soundscape selection. For example, the background node whose region of application is closest to the viewer is selected for a given view.

Nodes

All scene graph nodes have an implicit location in space of (0, 0, 0). For objects that exist in space, this implicit location provides a local coordinate system for that object, a fixed reference point. Even abstract objects that may not seem to have a well-defined location, such as behaviors and ambient lights, have this implicit location. An object's location provides an origin for its local coordinate system and, just as importantly, an origin for any bounding volume information associated with that object.

Live and/or Compiled

All scene graph objects, including nodes and node component objects, are either part of an active universe or not. An object is said to be live if it is part of an active universe. Additionally, branch graphs are either compiled or not. When a node is either live or compiled, Java 3D enforces access restrictions to nodes and node component objects. Java 3D allows only those operations that are enabled by the program before a node or node component becomes live or is compiled. It is best to set capabilities when you build your content. Listing 4 shows an example where we create a TransformGroup node and enable it for writing.

Listing 4 – Capabilities Example


TransformGroup myTrans = new TransformGroup();
myTrans.setCapability(Transform.ALLOW_TRANSFORM_WRITE);

By setting the capability to write the transform, Java 3D will allow the following code to execute:

myTrans.setTransform3D(myT3D);

It is important to ensure that all needed capabilities are set and that unnecessary capabilities are not set. The process of compiling a branch graph examines the capability bits and uses that information to reduce the amount of computation needed to run a program.