The Java 3D API Specification |
C H A P T E R7 |
Reusing Scene Graphs |
7.1
An application that wishes to share a subgraph from multiple places in a scene graph must do so through the use of the Link leaf node and an associated SharedGroup node. The SharedGroup node serves as the root of the shared subgraph. The Link leaf node refers to the SharedGroup node. It does not incorporate the shared scene graph directly into its scene graph.Sharing Subgraphs
7.1.1
A SharedGroup node allows multiple Link leaf nodes to share its subgraph (see Figure 7-1) according to the following semantics:SharedGroup Node
- A SharedGroup may be referenced by one or more Link leaf nodes. Any runtime changes to a node or component object in this shared subgraph affect all graphs that refer to this subgraph.
- A SharedGroup may be compiled by calling its
compile
method prior to being referenced by any Link leaf nodes.
- Only Link leaf nodes may refer to SharedGroup nodes. A SharedGroup node cannot have parents or be attached to a Locale.
Figure 7-1 Sharing a Subgraph
- Light
- Link
- Morph
- Shape
An
- Sound
IllegalSharingException
is thrown if any of the following leaf nodes appear in a shared subgraph:
- AlternateAppearance
- Background
- BoundingLeaf
- Behavior
- Clip
- Fog
- ModelClip
- Soundscape
- ViewPlatform
Constructors
public SharedGroup()Constructs and initializes a new SharedGroup node object.
Methods
The SharedGroup node defines the following methods:public void compile()This method compiles the source SharedGroup associated with this object and creates and caches a newly compiled scene graph.
7.1.2
The Link leaf node allows an application to reference a shared graph, rooted by a SharedGroup node, from within a branch graph or another shared graph. See Figure 7-1. Any number of Link nodes can refer to the same SharedGroup node.Link Leaf Node
Constants
The Link node object defines two flags.public static final int ALLOW_SHARED_GROUP_READ public static final int ALLOW_SHARED_GROUP_WRITEThese flags, when enabled using thesetCapability
method, allow an application to invoke methods that respectively read and write the SharedGroup node pointed to by this Link node. These capability flags are enforced only when the node is part of a live or compiled scene graph.
Constructors
The Link node object defines two constructors.public Link() public Link(SharedGroup sharedGroup)The first form constructs a Link node object that does not yet point to a SharedGroup node. The second form constructs a Link node object that points to the specified SharedGroup node.
Methods
The Link node object defines two methods.public void setSharedGroup(SharedGroup sharedGroup) public SharedGroup getSharedGroup()These methods access and modify the SharedGroup node associated with this Link leaf node.
7.2
An application developer may wish to reuse a common subgraph without completely sharing that subgraph. For example, the developer may wish to create a parking lot scene consisting of multiple cars, each with a different color. The developer might define three basic types of cars, such as convertible, truck, and sedan. To create the parking lot scene, the application will instantiate each type of car several times. Then the application can change the color of the various instances to create more variety in the scene. Unlike shared subgraphs, each instance is a separate copy of the scene graph definition: Changes to one instance do not affect any other instance.Cloning Subgraphs public Node cloneTree() public Node cloneTree(boolean forceDuplicate) public Node cloneTree(boolean forceDuplicate, boolean allowDanglingReferences) public Node cloneTree(NodeReferenceTable referenceTable) public Node cloneTree(NodeReferenceTable referenceTable, boolean forceDuplicate) public Node cloneTree(NodeReferenceTable referenceTable, boolean forceDuplicate, boolean allowDanglingReferences)These methods start the cloning of the subgraph. The optionalforceDuplicate
parameter, when set totrue
, causes leaf NodeComponent objects to ignore theirduplicateOnCloneTree
value and always be duplicated (see Section 7.2.1, "References to Node Component Objects"). TheallowDanglingReferences
parameter, when set totrue
, will permit the cloning of a subgraph even when a dangling reference is generated (see Section 7.2.3, "Dangling References"). SettingforceDuplicate
andallowDanglingReferences
tofalse
is the equivalent of callingcloneTree
without any parameters. This will result in NodeComponent objects being either duplicated or referenced in the cloned node, based on theirduplicateOnCloneTree
value. ADanglingReferenceException
will be thrown if a dangling reference is encountered.The
cloneTree
method cannot be called on a live or compiled scene graph.
7.2.1
WhenReferences to Node Component Objects cloneTree
reaches a leaf node, there are two possible actions for handling the leaf node's NodeComponent objects (such as Material, Texture, and so forth). First, the cloned leaf node can reference the original leaf node's NodeComponent object-the NodeComponent object itself is not duplicated. Since the cloned leaf node shares the NodeComponent object with the original leaf node, changing the data in the NodeComponent object will effect a change in both nodes. This mode would also be used for objects that are read-only at run time.Figure 7-2 shows two instances of NodeComponent objects that are shared and one NodeComponent element that is duplicated for the cloned subgraph.
Figure 7-2 Referenced and Duplicated NodeComponent Objects
public void setDuplicateOnCloneTree(boolean) public void getDuplicateOnCloneTree()These methods set a flag that controls whether a NodeComponent object is duplicated or referenced on a call tocloneTree
. By default this flag isfalse
, meaning that the NodeComponent object will not be duplicated on a call tocloneTree
-newly created leaf nodes will refer to the original NodeComponent object instead.
7.2.2
Leaf nodes that contain references to other nodes (for example, Light nodes reference a Group node) can create a problem for theReferences to Other Scene Graph Nodes cloneTree
method. After thecloneTree
operation is performed, the reference in the cloned leaf node will still refer to the node in the original subgraph-a situation that is most likely incorrect (see Figure 7-3).To handle these ambiguities, a callback mechanism is provided.
Figure 7-3 References to Other Scene Graph Nodes
Suppose, for instance, that the leaf node Lf1 in Figure 7-3 implemented the
updateNodeReferences
method. Once all nodes had been duplicated, theclone-Tree
method would then call each cloned leaf's nodeupdateNodeReferences
method. When cloned leaf node Lf2's method was called, Lf2 could ask if the node N1 had been duplicated during thecloneTree
operation. If the node had been duplicated, leaf Lf2 could then update its internal state with the cloned node, N2 (see Figure 7-4).
Figure 7-4 Updated Subgraph after updateNodeReferences Call
public void updateNodeReferences(NodeReferenceTable referenceTable)This SceneGraphObject node method is called by thecloneTree
method after all nodes in the subgraph have been cloned. The user can query the NodeReferenceTable object (see Section 7.2.5, "NodeReferenceTable Object") to determine if any nodes that the SceneGraphObject node references have been duplicated by thecloneTree
call and, if so, what the corresponding node is in the new subgraph. If a user extends a predefined Java 3D object and adds a reference to another node, this method must be defined in order to ensure proper operation of thecloneTree
method. The first statement in the user'supdateNodeReferences
method must besuper.updateNodeReferences(referenceTable)
. For predefined Java 3D nodes, this method will be implemented automatically.public final SceneGraphObject getNewObjectReference(SceneGraphObject oldReference)This method takes a reference to the node in the original subgraph as an input parameter and returns a reference to the equivalent node in the just-cloned subgraph. If the equivalent node in the cloned subgraph does not exist, either an exception is thrown or a reference to the original node is returned (see Section 7.2.3, "Dangling References").
7.2.3
BecauseDangling References cloneTree
is able to start the cloning operation from any node, there is a potential for creating dangling references. A dangling reference can occur only when a leaf node that contains a reference to another scene graph node is cloned. If the referenced node is not cloned, a dangling reference situation exists: There are now two leaf nodes that access the same node (Figure 7-5). A dangling reference is discovered when a leaf node'supdateNodeReferences
method calls thegetNewNodeReference
method and the cloned subgraph does not contain a counterpart to the node being looked up.
Figure 7-5 Dangling Reference: Bold Nodes Are Being Cloned
When a dangling reference is discovered,
cloneTree
can handle it in one of two ways. IfcloneTree
is called without theallowDanglingReferences
parameter set totrue
, a dangling reference will result in aDanglingReferenceException
being thrown. The user can catch this exception if desired. IfcloneTree
is called with theallowDanglingReferences
parameter set totrue
, theupdate-NodeReferences
method will return a reference to the same object passed into thegetNewNodeReference
method. This will result in thecloneTree
operation completing with dangling references, as in Figure 7-5.
7.2.4
All Java 3D predefined nodes (for example, Interpolators and LOD nodes) automatically handle all node reference and duplication operations. When a user subclasses a Leaf object or a NodeComponent object, certain methods must be provided in order to ensure the proper operation ofSubclassing Nodes cloneTree
.Node cloneNode(boolean forceDuplicate); void duplicateNode(Node n, boolean forceDuplicate)ThecloneNode
method consists of three lines:The
UserSubClass usc = new UserSubClass();
usc.duplicateNode(this, forceDuplicate);
return usc;duplicateNode
method must first callsuper.duplicateNode
before duplicating any necessary user-specific data or setting any user-specific state.NodeComponent cloneNodeComponent(); void duplicateNodeComponent(NodeComponent nc, boolean forceDuplicate);ThecloneNodeComponent
method consists of three lines:The
UserNodeComponent unc = new UserNodeComponent();
unc.duplicateNodeComponent(this, forceDuplicate);
return un;duplicateNodeComponent
must first callsuper.duplicateNodeComponent
and then can duplicate any user-specific data or set any user-specific state as necessary.
7.2.5
The NodeReferenceTable object is used by a leaf node'sNodeReferenceTable Object updateNodeReferences
method called by thecloneTree
operation. The NodeReferenceTable maps nodes from the original subgraph to the new nodes in the cloned subgraph. This information can than be used to update any cloned leaf node references to reference nodes in the cloned subgraph. This object can be created only by Java 3D.public NodeReferenceTable()Constructs an empty NodeReferenceTable.public SceneGraphObject getNewObjectReference(SceneGraphObject oldReference)This method takes a reference to the node in the original subgraph as an input parameter and returns a reference to the equivalent node in the just-cloned subgraph. If the equivalent node in the cloned subgraph does not exist, either an exception is thrown or a reference to the original node is returned (see Section 7.2.3, "Dangling References").
7.2.6
The following is an example of a user-defined Behavior object to show properly how to define a node to be compatible with theExample User Behavior Node cloneTree
operation.
class RotationBehavior extends Behavior { TransformGroup objectTransform; WakeupOnElapsedFrames w; Matrix4d rotMat = new Matrix4d(); Matrix4d objectMat = new Matrix4d(); Transform3D t = new Transform3D(); // Override Behavior's initialize method to set up wakeup // criteriapublic void initialize() { // Establish initial wakeup criteriawakeupOn(w); } // Override Behavior's stimulus method to handle the eventpublic void processStimulus(Enumeration criteria) { // Rotate by another PI/120.0 radiansobjectMat.mul(objectMat, rotMat); t.set(objectMat); objectTransform.setTransform(t); // Set wakeup criteria for next timewakeupOn(w); } // Constructor for rotation behavior.public RotationBehavior(TransformGroup tg, int numFrames) { w = new WakeupOnElapsedFrames(numFrames); objectTransform = tg; objectMat.setIdentity(); // Create a rotation matrix that rotates PI/120.0 // radians per frame rotMat.rotX(Math.PI/120.0); // Note: When this object is duplicated via cloneTree, // the cloned RotationBehavior node needs to point to // the TransformGroup in the just-cloned tree. } // Sets a new TransformGroup.public void setTransformGroup(TransformGroup tg) { objectTransform = tg; } // The next two methods are needed for cloneTree to operate // correctly. // cloneNode is needed to provide a new instance of the user // derived subclass.public Node cloneNode(boolean forceDuplicate) { // Get all data from current node needed for // the constructor int numFrames = w.getElapsedFrameCount(); RotationBehavior r = new RotationBehavior(objectTransform, numFrames); r.duplicateNode(this, forceDuplicate); return r; } // duplicateNode is needed to duplicate all super class // data as well as all user data.public void duplicateNode(Node originalNode, boolean forceDuplicate) { super.duplicateNode(originalNode, forceDuplicate); // Nothing to do here - all unique data was handled // in the constructor in the cloneNode routine. } // duplicateNode is needed to duplicate all super class // data as well as all user data.public void duplicateNode(Node originalNode, boolean forceDuplicate) { super.duplicateNode(originalNode, forceDuplicate); // Nothing to do here - all unique data was handled // in the constructor in the cloneNode routine.} // Callback for when this leaf is cloned. For this object // we want to find the cloned TransformGroup node that this // clone Leaf node should reference.public void updateNodeReferences(NodeReferenceTable t) { super.updateNodeReferences(t); // Update node's TransformGroup to proper referenceTransformGroup newTg = (TransformGroup)t.getNewObjectReference( objectTransform); setTransformGroup(newTg); } }
The Java 3D API Specification
Copyright © 2000, Sun Microsystems, Inc. All rights reserved.