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.
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.
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.
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.
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);
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);
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.
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 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.
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.