5.3 Bounds and CollisionBounds
It is time to look at usage examples and implementation hints and tips for the most commonly used scenegraph elements available in Java 3D. This chapter is intended to supplement the Sun Java 3D API documentation. Whether you are browsing or reading the book chapter by chapter, you may want to skim the detailed implementation advice and move ahead.
The Java 3D system supports the concept of a compiled scenegraph. Compilation is typically carried out after the scenegraph structure has been built, but before it is displayed. During compilation Java 3D analyzes the elements in the scenegraph, as well as the scenegraph structure, and attempts to perform optimizations to improve rendering time and scenegraph traversal.
Java 3D uses the capability bits that have been set on the scenegraph elements to identify which optimizations can be applied to the scenegraph. The capability bits that have been set for an object defines a contract between you (the application developer) and the Java 3D system. If, for example, you have not set the ALLOW_TRANSFORM_WRITE
capability on a TransformGroup
, the Java 3D system could use the fact that the 4 × 4 transformation matrix within the TransformGroup
remains constant to optimize rendering.
The use of capability bits is a powerful mechanism for adding complex optimizations in future versions of Java 3D. At present two main scenegraph optimizations have been implemented: attribute merging/sorting and geometry merging.
To take advantage of the benefits of compilation, you must override some of the default settings of the Shape3D
-derived objects in your scenegraph. In particular, the pickable
property is set by default for Shape3D
objects; objects with the pickable
property will not be optimized during the compile process.
The Appearances
assigned to Shape3D
objects in the scenegraph are computationally quite expensive for the scenegraph renderer. They take up memory, and when the renderer hits an Appearance
, it must make a long and complex series of OpenGL or DirectX calls to the rendering subsystem to add the information within the Appearance
to the rendering pipeline. Two optimizations can take place: duplicate Appearance
objects can be removed and replaced with a reference to a unique Appearance
object, and Shape3D
objects can be rendered in an order such that changes in Appearance
state are minimized. These optimizations reduce memory consumption and save on calls to the rendering subsystem. Obviously, only Appearance
objects that do not have any WRITE
capability bits set can be optimized using scenegraph compilation.
Geometry merging attempts to minimize the number of discrete Shape3D
objects in the scenegraph. A scenegraph will benefit from geometry merging if the Shape3D
objects fulfill the following criteria:
Shape3D
s with the same attributes and TGs
Shape3D
s that do not use indexed geometry
Shape3D
s with no capability bits set on their Appearance
s
Shape3D
s without the pickable
property
The compilation process will sort and attempt to merge the static subgraphs in the scenegraph. Dynamic subgraphs, that is, Nodes
with writable attributes (such as Group.ALLOW_CHILDREN_WRITE
), will have their static child Nodes
processed while ignoring the dynamic child Nodes
.
java.lang.Object | +--javax.media.j3d.SceneGraphObject | +--javax.media.j3d.Node
Node
is an abstract base class for Group
and Leaf Nodes
. It defines methods to control bounding volumes (through the Bounds
class), automatic computation of Bounds
, collision detection and picking (mouse selection). Most important, it allows each Node
to have a single parent Node
. The parent Node
allows arbitrarily complex scenegraph structures to be defined.
Group
-derived Nodes
have the ability to manage a Collection
of Node
-derived child objects, while Leaf
-derived Nodes
define the leaves of the scenegraph tree. In other words, Leaf Nodes
cannot have child Nodes
.
Java 3D maintains object boundary information for the Nodes
in the scenegraph. Every Node
in the scenegraph contains a Bounds
field that stores the geometric extent of the Node
. Java 3D uses the Node Bounds
information extensively, for everything from visibility testing to Behavior scheduling.
In addition, Shape3D
- and Group-derived objects in the scenegraph (i.e., all geometric objects and geometric container objects) contain the CollisionBounds
field. The Java 3D collision detection engine makes use of the CollisionBounds
field. A simplistic (and hence poor) collision detection algorithm would iterate through the objects in the scenegraph and test for an intersection between the CollisionBounds
for a Shape3D
object and the CollisionBounds
of every other Shape3D
object in the scenegraph.
There are three classes derived from Bounds: BoundingBox
, BoundingSphere
, and BoundingPolytope
. BoundingBox
defines a cuboidal volume of space; BoundingSphere
, a spherical volume of space; and BoundingPolytope
, a set of intersecting planes that define a closed, convex volume.
Node
-derived classes also have the option to autocompute their Bounds
. This option is enabled by default and allows geometric objects in the scenegraph, as well as their parents, to compute the Bounds
field based upon the positions of the geometric primitives (points, lines) from which they are composed.
Consult the following code snippets for the effects of creating an object with various combinations of Bounds
and/or CollisionBounds
.
From BoundsTest.java |
//use the defaults ColorCube cube0 = new ColorCube( 1.0 );
RESULTS |
BoundsAutoCompute: true Collidable: true Pickable: true Bounds: Bounding box: Lower=1.0 1.0 1.0 Upper=1.0 1.0 1.0 CollisionBounds: null |
Shape3D
objects are created as Collidable
and Pickable
, and they autocompute their Bounds
. No CollisionBounds
are assigned, so if collision detection functionality is required, the collision mode USE_GEOMETRY
should be used.
//explicitly set the Bounds using a BoundingBox ColorCube cube1 = new ColorCube( 2.0 ); cube1.setBoundsAutoCompute( false ); Bounds bounds = new BoundingBox( new Point3d( 2, 2, 2), new Point3d( 2, 2, 2 ) ); cube1.setBounds( bounds ); cube1.setCollisionBounds( bounds );
RESULTS |
BoundsAutoCompute: false Collidable: true Pickable: true Bounds: Bounding box: Lower = 2.0 2.0 2.0 Upper = 2.0 2.0 2.0 CollisionBounds: Bounding box: Lower = 2.0 2.0 2.0 Upper = 2.0 2.0 2.0 |
setBoundsAutoCompute( false )
, the Bounds
and CollisionBounds
for the Shape3D
object can be manually specified, as one would expect.
//explicitly set the Bounds using a BoundingSphere ColorCube cube2 = new ColorCube( 4.0 ); cube2.setBoundsAutoCompute( false ); bounds = new BoundingSphere( new Point3d( 0, 0, 0 ), 4 ); cube2.setBounds( bounds ); cube2.setCollisionBounds( bounds );
RESULTS |
BoundsAutoCompute: false Collidable: true Pickable: true Bounds: Bounding box: Lower = 4.0 4.0 4.0 Upper = 4.0 4.0 4.0 CollisionBounds: Center = (0.0, 0.0, 0.0) Radius = 4.0 |
BoundingSphere
is used to specify the Bounds
and CollisionBounds
for the Shape3D
object, the BoundingSphere
will be internally converted to a BoundingBox
and used for the Bounds
. The CollisionBounds
uses the original BoundingSphere
, however.
//auto compute, manual collision ColorCube cube3 = new ColorCube( 6.0 ); cube3.setBoundsAutoCompute( true ); bounds = new BoundingBox( new Point3d( 10, 10, 10 ), new Point3d( 10, 10, 10 ) ); cube3.setCollisionBounds( bounds );
RESULTS |
BoundsAutoCompute: true Collidable: true Pickable: true Bounds: Bounding box: Lower = 6.0 6.0 6.0 Upper = 6.0 6.0 6.0 CollisionBounds: Bounding box: Lower = 10.0 10.0 10.0 Upper = 10.0 10.0 10.0 |
//auto compute both ColorCube cube4 = new ColorCube( 6.0 ); cube4.setBoundsAutoCompute( true );
RESULTS |
BoundsAutoCompute: true Collidable: true Pickable: true Bounds: Bounding box: Lower = 6.0 6.0 6.0 Upper = 6.0 6.0 6.0 CollisionBounds: null |
There is a final piece to the Bounds
story. The scenegraph is a hierarchical data structure, so it makes sense for the Bounds
of a parent object to automatically encompass a volume large enough to hold all of its child objects. Java 3D can perform these calculations automatically, as table 5.1 illustrates (from BoundsTest.java).
Scenegraph item | Bounds | Autocompute |
---|---|---|
BranchGroup | null | false |
TransformGroup | Bounding Sphere: Center = (0.477, 0.34, 0.23) Radius = 11.00 | true |
RotationInterpolator | null | true |
Group1 | Center = (0.0,0.0, 0.0) Radius = 10.39 | true |
Cube1 | Bounding box: Lower = 1.0 1.0 1.0 Upper = 1.0 1.0 1.0 | true |
Cube2 | Bounding box: Lower = 2.0 2.0 2.0 Upper = 2.0 2.0 2.0 | true |
Cube3 | Bounding box: Lower = 4.0 4.0 4.0 Upper = 4.0 4.0 4.0 | true |
Cube4 | Bounding box: Lower = 6.0 6.0 6.0 Upper = 6.0 6.0 6.0 | true |
Cube5 | Bounding box: Lower = 6.0 6.0 6.0 Upper = 6.0 6.0 6.0 | true |
Group2 | Bounding Sphere: Center = (0.01,0.01,0.00) Radius = 8.62 | true |
PointsArray | Bounding box: Lower = 4.97 4.98 5.00 Upper = 4.95 4.96 4.97 | true |
Group1 contains the five ColorCubes
, as created earlier in the section. The largest ColorCube
has a BoundingBox
of (6,6,6) > (6,6,6). The radius of the smallest BoundingSphere
to enclose the largest ColorCube
is therefore radius = sqrt( 62 + 62 + 62) = 10.392. This BoundingSphere
is automatically created by Java 3D and assigned to the parent Group
(Group1) of the ColorCubes
. Note that Group1 has the property setBoundsAutoCompute( true )
.
Group2 contains a Shape3D
object composed from 200 random points in a PointArray
(positioned between 5 and 5 in the x-, y-, and z-axes). Java 3D automatically creates a BoundingBox
to enclose the points composing the Shape3D
objectapproximately: (5,5,5) > (5,5,5). The BoundingBox
is automatically assigned to the Shape3D
object containing the PointArray
. The Bounds
for the Shape3D
object are propagated up the scenegraph hierarchy as a BoundingSphere
and assigned to Group2. The center of the BoundingSphere
is positioned to minimize the radius (in this case approximately 0,0,0). The radius of the BoundingSphere
is approximately computed from radius = sqrt( 52 + 52 + 52) = 8.660.
The parent of Group1, Group2, and RotationInterpolator
is TransformGroup
. TransformGroup
combines the Bounds
objects for its children to compute its own Bounds
. In this case, as the Bounds
of the children are all approximately centered at (0,0,0), which is equal to the Bounds of Group1 (which is the largest).
NOTE | The top-level parent BranchGroup node has the attribute setBoundsAutoCompute( false ) .
|
//routine to create a Shape3D object made from a point cloud //of 200 random points protected Group createPoints() { Group group = new Group();
final int kNumPoints = 200; final double kRadius = 10.0; Point3d points[] = new Point3d[kNumPoints];
for( int n = 0; n < kNumPoints; n++ ) { double randX = (java.lang.Math.random() * kRadius ) kRadius/2; double randY = (java.lang.Math.random() * kRadius ) kRadius/2; double randZ = (java.lang.Math.random() * kRadius ) kRadius/2;
points[n] = new Point3d( randX, randY, randZ ); }
PointArray pointArray = new PointArray( points.length, GeometryArray.COLOR_4 | GeometryArray.COORDINATES ); pointArray.setCoordinates( 0, points );
Shape3D shapePoints = new Shape3D( pointArray, new Appearance() );
group.addChild( shapePoints ); return group; }
Note that the propagation of Bounds
up the scenegraph hierarchy (from child to parent) does not occur with CollisionBounds
. Cube4 has CollisionBounds
of (10,10,10) > (10,10,10) but these do not influence the Bounds
of the parent Group1. Surprisingly, the CollisionBounds
of Cube4 do not influence the CollisionBounds
of the parent Group1 either. It appears that the application programmer is responsible for manually propagating CollisionBounds
from child to parent Node
s.
java.lang.Object | +--javax.media.j3d.SceneGraphObject | +--javax.media.j3d.Node | +--javax.media.j3d.Group
Group
defines a scenegraph Node
that contains a collection of child Node
s. It defines the following child Node
management methods:
void addChild(Node child) java.util.Enumeration getAllChildren() Node getChild(int index) void insertChild(Node child, int index) void moveTo(BranchGroup branchGroup) int numChildren() void removeChild(int index) void setChild(Node child, int index)
These methods essentially delegate, in obvious ways, to the internal collection that manages the child Node
s within the Group
. Table 5.2 shows the capabilities defined by Group
.
Capability bit | Description |
---|---|
ALLOW_CHILDREN_EXTEND | Allows child Nodes to be added to the Group |
ALLOW_CHILDREN_READ | Allows reading of child Nodes (e.g., getChild method) |
ALLOW_CHILDREN_WRITE | Allows writing of child Nodes (e.g., setChild method) |
ALLOW_COLLISION_BOUNDS_READ | Allows reading of collision Bounds |
ALLOW_COLLISION_BOUNDS_WRITE | Allows writing of collision Bounds |
Group
is an important base class for the Java 3D Node
management classes, and it can also be instantiated in its own right. For increased flexibility, however, I recommend BranchGroup Nodes
because they can be dynamically added or removed from the scenegraph. The classes derived from Group
are shown in table 5.3.
Class | Description |
---|---|
BranchGroup | A dynamically insertable and removable Group |
OrderedGroup | A Group that renders its children in a defined order, irrespective of location |
Primitive | A geometric Group used to manage geometry in the utils package |
SharedGroup | A Group that can be reused across the scenegraph and can be attached to multiple parents |
Switch | A Group that can conditionally display its child Nodes |
TransformGroup | A Group that has an associated geometric transformation containing rotation, translation, and scale information that is applied to its child Nodes before rendering |
Note that an instance of any of the Group
-derived classes, including SharedGroup
, can only be added to a single location within the scenegraph. Attempting to add a scenegraph node to a scenegraph that already has an assigned parent (i.e., a node that has already been added to the scenegraph) will result in a run-time exception. I discuss reusing scenegraph branches using a SharedGroup
and a Link
later in this chapter.
It is useful to be able to remove a child Node
from its parent Group
without knowing the child Node
s index. Unfortunately, because scenegraph Nodes
are removed from a Group
using void removeChild(int index)
, there is no easy way to remove a Shape3D
object from a Group
if you do not know the index at which it was originally inserted. In the following example, I remove a Shape3D
object that corresponds to the internal, application-specific data structure. By storing the application-specific data structure in the UserData
field of the Shape3D
, I can retrieve the index of the Shape3D
and remove it from its parent Group
object.
ClassificationObject
is an application-specific data structure that is stored in each child Node
to identify it. To store the ClassificationObject
in the Node, use
node.setUserData( classificationObject );
public void removeChildObject( ClassificationObject targetObj ) { //we need to remove the object by index, so we have to iterate //through our objects to find it.
//get an enumeration containing all the child nodes Enumeration enum = getAllChildren();
int nIndex = 0; Node obj = null;
//scan through the child nodes until we find the one that //corresponds to our data structure. while( enum.hasMoreElements() != false ) { obj = (Node) enum.nextElement();
if( targetObj != obj.getUserData() ) nIndex++; else break; }
//if we found the object, we can now remove it by index. if( nIndex < numChildren() ) removeChild( nIndex ); else System.out.println( "Failed to find child object during remove operation." ); }
Note that in the preceding example, the implicit this
is an instance of a class derived from Group
that has the capability to remove child Node
s based on an internal data structure.
java.lang.Object | +--javax.media.j3d.SceneGraphObject | +--javax.media.j3d.Node | +--javax.media.j3d.Group | +--javax.media.j3d.Switch
The Switch Node
provides the facility to define a Group Node
that can conditionally display or hide its child Node
s (see table 5.4).
Effect | Usage example |
---|---|
All child Nodes | new Switch( Switch.CHILD_ALL ) |
No child Nodes | new Switch( Switch.CHILD_NONE ) |
A single child Node | switchNode.setWhichChild( nIndex ) |
Specifiable child Nodes | new Switch( Switch.CHILD_MASK ), switchNode.setChildMask( java.util.BitSet childMask ) |
For example, to create a Switch Node
that displays child Nodes
at index 3, 6, and 7 use the following:
From SwitchTest.java |
//create the Switch Node Switch switchGroup = new Switch( Switch.CHILD_MASK ); switchGroup.setCapability( Switch.ALLOW_SWITCH_WRITE );
switchGroup.addChild( createLabel( "Child Node 1", labelScale ) ); switchGroup.addChild( createLabel( "Child Node 2", labelScale ) ); switchGroup.addChild( createLabel( "Child Node 3", labelScale ) ); switchGroup.addChild( createLabel( "Child Node 4", labelScale ) ); switchGroup.addChild( createLabel( "Child Node 5", labelScale ) ); switchGroup.addChild( createLabel( "Child Node 6", labelScale ) ); switchGroup.addChild( createLabel( "Child Node 7", labelScale ) );
//create the logical mask to control Node visibility java.util.BitSet visibleNodes = new java.util.BitSet( switchGroup.numChildren() );
//make the third, sixth and seventh nodes visible visibleNodes.set( 2 ); visibleNodes.set( 5 ); visibleNodes.set( 6 );
//assign the visibility mask to the Switch switchGroup.setChildMask( visibleNodes );
The output of the SwitchTest example is shown in figure 5.1.
Figure 5.1 The effect of using a BitSet mask and a Switch Node. On the left, the Switch Node has been created with theSwitch.CHILD_ALL
attribute. On the right, a BitSet has been created to display the third, sixth, and seventh Node
through a call to setChildMask
. The child elements being controlled by the Switch Node are Text2D
objects
The Switch Node
can be used to implement modal static scenegraphs, that is, scenegraphs that are essentially of a fixed structure but which the user can influence through adding or removing prebuilt sections.
Switch Nodes
can also be used to implement simple animation using the SwitchInterpolator Behavior
(figure 5.2). The SwitchInterpolator
attaches to a Switch Node
and cycles the active child of the Switch Node
using an Alpha
object. For example, a simple 3D flip-book style animation could be achieved by adding several versions of a 3D model to a Switch Node
and triggering a SwitchInterpolator
to cycle from one model to another.
Switch Node
is created with seven child elements, and a SwitchInterpolator is used to cycle between them. Note that the items at index 3 (row 2, column 1) and 6 (row 3, column 1) use a Link
Node to share a single SharedGroup
BEWARE |
If you choose to use the SwitchInterpolator class, do not add the Interpolator as a child of the Switch Node itself, or the moment the Interpolator is activated it will deactivate itself, hence stopping the Interpolator . |
java.lang.Object | +--javax.media.j3d.SceneGraphObject | +--javax.media.j3d.Node | +--javax.media.j3d.Group | +--javax.media.j3d.BranchGroup
BranchGroup
defines a Group Node
that can be dynamically inserted or removed from a parent Group
at runtime. In addition the root parent Group
of the scenegraph must be a BranchGroup
since only BranchGroups
can be inserted into a Locale
.
To allow a BranchGroup
to be dynamically removed from its parent, the BranchGroup
must have the BranchGroup.ALLOW_DETACH
capability set. To allow a BranchGroup
to be dynamically inserted (or attached) into a parent Group
the Group
must have the capability Group.ALLOW_CHILDREN_EXTEND
. Why these capabilities have been divided between the Group
and BranchGroup
classes is not quite clear.
BranchGroups
are typically used as return values by the methods that build the various components of an application scenegraph. For example, an F1 racing application might define the following abstract class:
abstract class F1Object extends Object { BranchGroup m_BranchGroup = null;
public F1Object(); protected BranchGroup createBranchGroup();
public getBranchGroup() { if( m_BranchGroup == null ) m_BranchGroup = createBranchGroup();
return m_BranchGroup; } }
The F1Object
abstract class forces the application developer to define the createBranchGroup
virtual method in a derived class. The createBranchGroup
method is responsible for creating a BranchGroup
containing the child Nodes
required to define the Geometry
and Behaviors
for the F1Object
being created. This very simple OO design allows an F1Object Manager
class to be defined that maintains a Vector
(or List
or Map
) of generic F1Objects
and is responsible for their creation and removal from the applications scenegraph. The objects derived from F1Object
are themselves easily reusable because their geometry generation and management routines are all packages with the class itself. The setUserData
method (defined in the section on Group Nodes
) can be used to track F1Object
instances once they have been inserted into the scenegraph.
java.lang.Object | +--javax.media.j3d.SceneGraphObject | +--javax.media.j3d.Node | +--javax.media.j3d.Group | +--javax.media.j3d.OrderedGroup
The OrderedGroup Node
is a less commonly used scenegraph element. It allows an application developer to have basic control over the rendering order of the children of a Group Node
.
An OrderedGroup
(or DecalGroup
which is derived from OrderedGroup
) can be useful for defining the rendering order for essentially coplanar surfaces, such as a road lying on terrain, or a cloth covering a table (figure 5.3). Note that both of these examples make implicit assumptions about the range of possible viewing angles for the objects, if the viewer can sit underneath the table, the tablecloth should not be rendered before the table! Other uses for an OrderedGroup
might be to implement signs or labels for geometric objectsthe labels should always be rendered on top of the objects they are labeling, irrespective of the viewers position.
Nodes
using an OrderedGroup
. The item at index 0 (a Text2D object with the text 3. OrderedGroup), overlaps the item at index 1 (Child 1), which overlaps the item at index 2 (Child 2)
From NodesTest.java |
OrderedGroup orderedGroup = new OrderedGroup(); orderedGroup.addChild ( createLabel( "3. OrderedGroup", labelScale ) ); orderedGroup.addChild( createLabel( "Child 1", labelScale ) ); orderedGroup.addChild( createLabel( "Child 2", labelScale ) );
java.lang.Object | +--javax.media.j3d.SceneGraphObject | +--javax.media.j3d.Node | +--javax.media.j3d.Group | +--javax.media.j3d.SharedGroup
The SharedGroup Node
defines a scenegraph management Node
that can be attached to several parent Nodes
. The SharedGroup
itself can be arbitrarily complex but must occur (as a whole) as a Leaf Node
within the scenegraph. A SharedGroup
must be wrapped in an instance of a Link
object before being added to the scenegraph. The Link
must have one unique parent.
SharedGroup
s cannot contain the following Nodes
:
java.lang.Object | +--javax.media.j3d.SceneGraphObject | +--javax.media.j3d.Node | +--javax.media.j3d.Leaf | +--javax.media.j3d.Link
The Link Node
is used in association with a SharedGroup
. Since the SharedGroup
can appear in several locations in the scenegraph, and a Node
object can only have a single parent Node
, a unique Link Node
must be used as a placeholder within the scenegraph for the SharedGroup Node
. When the scenegraph is traversed, and the Link Node
is encountered, the traversal algorithm will step into the SharedGroup
that is internally referenced by the Link Node
(figure 5.4).
Switch Node
with two child Link Nodes
. Both Link Nodes reference the same SharedGroup
(SG). This type of structure is not possible without using Link Nodes
as a single Node
can only have one parent Node
From NodesTest.java |
//create the SharedGroup SharedGroup sharedGroup1 = new SharedGroup();
//add geometry to the SharedGroup sharedGroup1.addChild ( createLabel( "4. Shared Group 1", labelScale ) );
//add the first Link for the SharedGroup switchGroup.addChild( new Link( sharedGroup1 ) );
//add the second Link for the SharedGroup switchGroup.addChild( new Link( sharedGroup1 ) );
//Note. The InterpolatorTest example also uses SharedGroups //and Link Nodes in a more substantial manner.
SharedGroups
can be very useful in minimizing the memory footprint of an application because a single SharedGroup
can be referenced hundreds of times within a scenegraph to position repeating geometry within a scene.
java.lang.Object | +--javax.media.j3d.SceneGraphObject | +--javax.media.j3d.Node | +--javax.media.j3d.Group | +--com.sun.j3d.utils.geometry.Primitive
Primitive
is a Group
-derived class that serves as the base class for the geometric primitives (Box
, Sphere
, Cone
, etc.) that are defined in the Java 3D utils
package. Objects of the Primitive
class should not be instantiated directly, and the Primitive
class is very difficult to extend usefully. For a full discussion of the Primitive
class, see chapter 8.
java.lang.Object | +--javax.media.j3d.SceneGraphObject | +--javax.media.j3d.Node | +--javax.media.j3d.Group | +--javax.media.j3d.TransformGroup
The TransformGroup Node
is central to almost all scenegraph designs. A TransformGroup
incorporates the rotation, translation, and scaling information that is applied to all of its child Node
s. Without the TransformGroup
, scenegraphs would be static, always positioned at 0,0,0, uniformly unit scaled, and without rotation about any of the axes. Not a very interesting interactive scene.
The TranformGroup
controls orientation of its child Node
s through the Transform3D
object that it encapsulates (figure 5.5). The Transform3D
object represents such transformations using a typical 4 × 4 transformation matrix. The 4 × 4 matrix of double precision numbers allows scaling, rotation, and translation information to be stored and applied by a single matrix.
TransformGroup
is used to rotate a ColorCube and Text2D label to a desired orientation
A detailed understanding of the mathematics behind the Transform3D
object is very useful, but is beyond the scope of this book. Some useful references for mathematics for 3D graphics are presented in appendix B. Transform3D
includes methods that allow application developers to apply transformations while remaining largely ignorant of the underlying implementation.
This chapter has introduced many of the Node
types available in Java 3D. The Java 3D Nodes
cover the basic requirements of most scenegraphs:
Nodes
into logical units (Group
)
BranchGroup
)
Group
(OrderedGroup
)
SharedGroup
and Link
)
TransformGroup
)
Armed with the information in chapters 4 and 5 you should be able to tackle the high-level scenegraph design for your application. The chapters to come will also be very useful, as we start to discuss how the scenegraph fits into the Java 3D VirtualUniverse
as well as the rendering model (chapter 6), the data model for your application (chapter 7), and Java 3Ds geometry description capabilities (chapter 8).