The Java 3D API Specification |

C H A P T E R 10

Behaviors and Interpolators

> BEHAVIOR nodes provide the means for animating objects, processing keyboard and mouse inputs, reacting to movement, and enabling and processing pick events. Behavior nodes contain Java code and state variables. A Behavior node's Java code can interact with Java objects, change node values within a Java 3D scene graph, change the behavior's internal state-in general, perform any computation it wishes.

> Simple behaviors can add surprisingly interesting effects to a scene graph. For example, one can animate a rigid object by using a Behavior node to repetitively modify the TransformGroup node that points to the object one wishes to animate. Alternatively, a Behavior node can track the current position of a mouse and modify portions of the scene graph in response.

> ## 10.1 Behavior Object

> A Behavior leaf node object contains a scheduling region and two methods: an `initialize` method called once when the behavior becomes "live" and a `processStimulus` method called whenever appropriate by the Java 3D behavior scheduler. The Behavior object also contains the state information needed by its `initialize` and `processStimulus` methods.

> The scheduling region defines a spatial volume that serves to enable the scheduling of Behavior nodes. A Behavior node is active (can receive stimuli) whenever a ViewPlatform's activation volume intersects a Behavior object's scheduling region. Only active behaviors can receive stimuli.

> The `initialize` method allows a Behavior object to initialize its internal state and specify its initial wakeup condition(s). Java 3D invokes a behavior's initialize code when the behavior's containing BranchGroup node is added to the virtual universe. Java 3D does not invoke the `initialize` method in a new thread. Thus, for Java 3D to regain control, the `initialize` method must not execute an infinite loop: It must return. Furthermore, a wakeup condition must be set or else the behavior's `processStimulus` method is never executed.

> The `processStimulus` method receives and processes a behavior's ongoing messages. The Java 3D behavior scheduler invokes a Behavior node's `processStimulus` method when a ViewPlatform's activation volume intersects a Behavior object's scheduling region and all of that behavior's wakeup criteria are satisfied. The `processStimulus` method performs its computations and actions (possibly including the registration of state change information that could cause Java 3D to wake other Behavior objects), establishes its next wakeup condition, and finally exits.

> ### 10.1.1 Code Structure

> When the Java 3D behavior scheduler invokes a Behavior object's `processStimulus` method, that method may perform any computation it wishes. Usually, it will change its internal state and specify its new wakeup conditions. Most probably, it will manipulate scene graph elements. However, the behavior code can change only those aspects of a scene graph element permitted by the capabilities associated with that scene graph element. A scene graph's capabilities restrict behavioral manipulation to those manipulations explicitly allowed.

> The application must provide the Behavior object with references to those scene graph elements that the Behavior object will manipulate. The application provides those references as arguments to the behavior's constructor when it creates the Behavior object. Alternatively, the Behavior object itself can obtain access to the relevant scene graph elements either when Java 3D invokes its `initialize` method or each time Java 3D invokes its `processStimulus` method.

> Behavior methods have a very rigid structure. Java 3D assumes that they always run to completion (if needed, they can spawn threads). Each method's basic structure consists of the following:

> - Code to decode and extract references from the WakeupCondition enumeration that caused the object's awakening.

> - Code to perform the manipulations associated with the WakeupCondition.

> - Code to establish this behavior's new WakeupCondition.

> - A path to Exit (so that execution returns to the Java 3D behavior scheduler).

> ### 10.1.2 WakeupCondition Object

> A WakeupCondition object is an abstract class specialized to fourteen different WakeupCriterion objects and to four combining objects containing multiple WakeupCriterion objects.

> A Behavior node provides the Java 3D behavior scheduler with a WakeupCondition object. When that object's WakeupCondition has been satisfied, the behavior scheduler hands that same WakeupCondition back to the Behavior via an enumeration.

> ### 10.1.3 WakeupCriterion Object

> Java 3D provides a rich set of wakeup criteria that Behavior objects can use in specifying a complex WakeupCondition. These wakeup criteria can cause Java 3D's behavior scheduler to invoke a behavior's `processStimulus` method whenever

> - The center of a ViewPlatform enters a specified region.

> - The center of a ViewPlatform exits a specified region.

> - A behavior is activated.

> - A behavior is deactivated.

> - A specified TransformGroup node's transform changes.

> - Collision is detected between a specified Shape3D node's Geometry object and any other object.

> - Movement occurs between a specified Shape3D node's Geometry object and any other object with which it collides.

> - A specified Shape3D node's Geometry object no longer collides with any other object.

> - A specified Behavior object posts a specific event.

> - A specified AWT event occurs.

> - A specified time interval elapses.

> - A specified number of frames have been drawn.

> - The center of a specified Sensor enters a specified region.

> - The center of a specified Sensor exits a specified region.

> A Behavior object constructs a WakeupCriterion by constructing the appropriate criterion object. The Behavior object must provide the appropriate arguments (usually a reference to some scene graph object and possibly a region of interest). Thus, to specify a WakeupOnViewPlatformEntry, a behavior would specify the region that will cause the behavior to execute if a ViewPlatform enters it.

> ### 10.1.4 Composing WakeupCriterion Objects

> A Behavior object can combine multiple WakeupCriterion objects into a more powerful, composite WakeupCondition. Java 3D behaviors construct a composite WakeupCondition in one of the following ways:

> - WakeupAnd: An array of WakeupCriterion objects ANDed together.

>                 WakeupCriterion && WakeupCriterion && ...

> - WakeupOr: An array of WakeupCriterion objects ORed together.

>                 WakeupCriterion || WakeupCriterion || ...

> - WakeupAndOfOrs: An array of WakeupOr WakeupCondition objects that are then ANDed together.

>                 WakeupOr && WakeupOr && ...

> - WakeupOrOfAnds: An array of WakeupAnd WakeupCondition objects that are then ORed together.

>                 WakeupAnd || WakeupAnd || ...

> ## 10.2 Composing Behaviors

> Behavior objects can condition themselves to awaken only when signaled by another Behavior node. The WakeupOnBehaviorPost WakeupCriterion takes as arguments a reference to a Behavior node and an integer. These two arguments allow a behavior to limit its wakeup criterion to a specific post by a specific behavior.

> The WakeupOnBehaviorPost WakeupCriterion permits behaviors to chain their computations, allowing parenthetical computations-one behavior opens a door and the second closes the same door, or one behavior highlights an object and the second unhighlights the same object.

> ## 10.3 Scheduling

> As a virtual universe grows large, Java 3D must carefully husband its resources to ensure adequate performance. In a 10,000-object virtual universe with 400 or so Behavior nodes, a naive implementation of Java 3D could easily end up consuming the majority of its compute cycles in executing the behaviors associated with the 400 Behavior objects before it draws a frame. In such a situation, the frame rate could easily drop to unacceptable levels.

> Behavior objects are usually associated with geometric objects in the virtual universe. In our example of 400 Behavior objects scattered throughout a 10,000-object virtual universe, only a few of these associated geometric objects would be visible at a given time. A sizable fraction of the Behavior nodes-those associated with nonvisible objects-need not be executed. Only those relatively few Behavior objects that are associated with visible objects must be executed.

> Java 3D mitigates the problem of a large number of Behavior nodes in a high-population virtual universe through execution culling-choosing to invoke only those behaviors that have high relevance.

> Java 3D requires each behavior to have a scheduling region and to post a wakeup condition. Together a behavior's scheduling region and wakeup condition provide Java 3D's behavior scheduler with sufficient domain knowledge to selectively prune behavior invocations and invoke only those behaviors that absolutely need to be executed.

> ## 10.4 How Java 3D Performs Execution Culling

> Java 3D finds all scheduling regions associated with Behavior nodes and constructs a scheduling/volume tree. It also creates an AND/OR tree containing all the Behavior node wakeup criteria. These two data structures provide the domain knowledge Java 3D needs to prune unneeded behavior execution (to perform "execution triage").

> Java 3D must track a behavior's wakeup conditions only if a ViewPlatform object's activation volume intersects with that Behavior object's scheduling region. If the ViewPlatform object's activation volume does not intersect with a behavior's scheduling region, Java 3D can safely ignore that behavior's wakeup criteria.

> In essence, the Java 3D scheduler performs the following checks:

> - Find all Behavior objects with scheduling regions that intersect the ViewPlatform object's activation volume.

> - For each Behavior object within the ViewPlatform's activation volume, if that behavior's WakeupCondition is `true`, schedule that Behavior object for execution.

> Java 3D's behavior scheduler executes those Behavior objects that have been scheduled by calling the behavior's `processStimulus` method.

> ## 10.5 The Behavior API

> The Java 3D behavior API spreads its functionality across three objects: the Behavior leaf node, the WakeupCondition object and its subclasses, and the WakeupCriterion objects.

> ### 10.5.1 The Behavior Node

> The Behavior object is an abstract class that contains the framework for all behavioral components in Java 3D.

> ##### Constructor

> The Behavior leaf node class defines the following constructor:

>     public Behavior()

> Constructs a Behavior node with default parameters:

> Parameter | Default Value
> --- | ---
> enable flag | true
> schedulingBounds | null
> schedulingBoundingLeaf | null

> ##### Methods

> The Behavior leaf node class defines the following methods:

>     public abstract void initialize()

> This method, invoked by Java 3D's behavior scheduler, is used to initialize the behavior's state variables and to establish its WakeupConditions. Classes that extend Behavior must provide their own `initialize` method. Applications should not call this method.

>     public abstract void processStimulus(Enumeration criteria)

> This method processes stimuli destined for this behavior. The behavior scheduler invokes this method if its WakeupCondition is satisfied. Classes that extend Behavior must provide their own `processStimulus` method. Applications should not call this method.

>     public void setSchedulingBounds(Bounds region)
>     public Bounds getSchedulingBounds()

> These two methods access or modify the Behavior node's scheduling bounds. This bounds is used as the scheduling region when the scheduling bounding leaf is set to `null`. A behavior is scheduled for activation when its scheduling region intersects the ViewPlatform's activation volume (if its wakeup criteria have been satisfied). The `getSchedulingBounds` method returns a copy of the associated bounds.

>     public void setSchedulingBoundingLeaf(BoundingLeaf region)
>     public BoundingLeaf getSchedulingBoundingLeaf()

> These two methods access or modify the Behavior node's scheduling bounding leaf. When set to a value other than `null`, this bounding leaf overrides the scheduling bounds object and is used as the scheduling region.

>     protected void wakeupOn(WakeupCondition criteria)

> This method defines this behavior's wakeup criteria. This method may be called only from a Behavior object's `initialize` or `processStimulus` methods to (re)arm the next wakeup. It should be the last thing done by those methods.

>     public void postId(int postId)

> This method, when invoked by a behavior, informs the Java 3D scheduler of the identified event. The scheduler will schedule other Behavior objects that have registered interest in this posting.

>     protected View getView()

> This method returns the primary view associated with this behavior. This method is useful with certain types of behaviors, such as Billboard and LOD, that rely on per-View information and with behaviors in general in regards to scheduling (the distance from the view platform determines the active behaviors). The "primary" view is defined to be the first View attached to a live ViewPlatform, if there is more than one active View. So, for instance, Billboard behaviors would be oriented toward this primary view, in the case of multiple active views into the same scene graph.

> ### 10.5.2 WakeupCondition Object

> WakeupCondition is an abstract class that is extended by the WakeupCriterion, WakeupOr, WakeupAnd, WakeupOrOfAnds, and WakeupAndOfOr classes. A Behavior node hands a WakeupCondition object to the behavior scheduler, and the behavior scheduler hands back an enumeration of that WakeupCondition.

> ##### Methods

> The Java 3D API provides two methods for constructing WakeupCondition enumerations:

>     public Enumeration allElements()
>     public Enumeration triggeredElements()

> These two methods create enumerators that sequentially access this WakeupCondition's wakeup criteria. The first method creates an enumerator that sequentially presents all wakeup criteria that were used to construct this WakeupCondition. The second method creates an enumerator that sequentially presents only those wakeup criteria that have been satisfied.

> ### 10.5.3 The WakeupCriterion Objects

> WakeupCriterion is an abstract class that consists of several subclasses. Each subclass specifies one particular wakeup criterion, that criterion's associated arguments (if any), and either a flag that indicates whether this criterion caused a Behavior object to awaken or a return field containing the information that caused the Behavior object to awaken.

> ##### Methods

>     public boolean hasTriggered()

> This predicate method returns `true` if this WakeupCriterion contributed to waking a Behavior object.

> #### 10.5.3.1 WakeupOnAWTEvent

> This WakeupCriterion object specifies that Java 3D should awaken a behavior when the specified AWT event occurs.

> ##### Constructors

>     public WakeupOnAWTEvent(int AWTId)
>     public WakeupOnAWTEvent(long eventMask)

> The first constructor creates a WakeupOnAWTEvent object that informs the Java 3D scheduler to wake up the specified Behavior object whenever the AWT event specified by `AWTId` occurs. The second constructor creates a WakeupOnAWTEvent object that informs the Java 3D scheduler to wake up the specified Behavior object whenever any of the specified AWT `EVENT_MASK` events occur. The `eventMask` consists of an ORed collection of `EVENT_MASK` values.

> ##### Methods

>     public AWTEvent[] getAWTEvent()

> This method returns the array of consecutive AWT events that triggered this WakeupCriterion to awaken the Behavior object. The Behavior object can retrieve the `AWTEvent` array and process it in any way it wishes.

> #### 10.5.3.2 WakeupOnActivation

> The WakeupOnActivation object specifies a wakeup the first time the ViewPlatform's activation region intersects with this object's scheduling region. This gives the behavior an explicit means of executing code when it is activated.

> ##### Constructors

>     public WakeupOnActivation()

> This constructor creates a WakeupOnActivation criterion.

> #### 10.5.3.3 WakeupOnBehaviorPost

> This WakeupCriterion object specifies that Java 3D should awaken this behavior when the specified behavior posts the specified ID.

> ##### Constructors

>     public WakeupOnBehaviorPost(Behavior behavior, int postId)

> This constructor creates a WakeupOnBehaviorPost object that informs the Java 3D scheduler to wake up this Behavior object whenever the specified behavior posts the specified `postId`. A `postId` of 0 specifies that this behavior should awaken on any post from the specified behavior. Specifying a `null` behavior implies that this behavior should awaken whenever any behavior posts the specified `postId`.

> ##### Methods

>     public int getPostId()

> This method returns the `postId` used in creating this WakeupCriterion.

>     public Behavior getBehavior()

> This method returns the behavior specified in this object's constructor.

>     public int getTriggeringPostId()

> This method returns the postid that caused the behavior to wake up. If the postid used to construct this wakeup criterion was not zero, the triggering postid will always be equal to the postid used in the constructor.

>     public Behavior getTriggeringBehavior()

> This method returns the behavior that triggered this wakeup. If the arming behavior used to construct this object was not null, the triggering behavior will be the same as the arming behavior.

> #### 10.5.3.4 WakeupOnDeactivation

> The WakeupOnDeactivation object specifies a wakeup on the first detection of a ViewPlatform's activation region no longer intersecting with this object's scheduling region. This gives the behavior an explicit means of executing code when it is deactivated.

> ##### Constructors

>     public WakeupOnDeactivation()

> This constructor creates a new WakeupOnDeactivation criterion.

> #### 10.5.3.5 WakeupOnElapsedFrames

> This WakeupCriterion object specifies that Java 3D should awaken this behavior after it has rendered the specified number of frames. A value of 0 implies that Java 3D will awaken this behavior at the next frame. The wakeup criterion can be either passive or nonpassive. If a behavior uses a nonpassive WakeupOn-ElapsedFrames, the rendering system will run continuously.

> ##### Constructors

>     public WakeupOnElapsedFrames(int frameCount)

> This constructor creates a nonpassive WakeupOnElapsedFrames object that informs the Java 3D scheduler to wake up the specified Behavior object after it has drawn `frameCount` frames. A `frameCount` value of N means wake up at the end of frame N, where the current frame is 0. A `frameCount` value of 0 means wake up at the end of the current frame.

>     public WakeupOnElapsedFrames(int frameCount, boolean passive)

> This constructor creates a WakeupOnElapsedFrames criterion. The `passive` flag indicates whether this behavior is passive. A nonpassive behavior will cause the rendering system to run continuously. A passive behavior will run only when some other event causes a frame to be run.

> ##### Methods

>     public int getElapsedFrameCount()

> This method returns the frame count that was specified when constructing this object.

>     public boolean isPassive()

> This method retrieves the state of the passive flag that was used when constructing this object.

> #### 10.5.3.6 WakeupOnElapsedTime

> This WakeupCriterion object specifies that Java 3D should awaken this behavior after an elapsed number of milliseconds.

> ##### Constructors

>     public WakeupOnElapsedTime(long milliseconds)

> This constructor creates a WakeupOnElapsedTime object that informs the Java 3D scheduler to wake up the specified Behavior object after the specified number of milliseconds.

> Note: The Java 3D scheduler will schedule the object after the specified number of milliseconds have elapsed, not before. However, the elapsed time may actually be slightly greater than the time specified.

> ##### Methods

>     public long getElapsedFrameTime()

> This method returns the WakeupCriterion's elapsed time value in milliseconds.

> #### 10.5.3.7 WakeupOnSensorEntry

> This WakeupCriterion object specifies that Java 3D should awaken this behavior when any sensor enters the specified region.

> Note: There can be situations in which a sensor may enter and then exit an armed region so rapidly that neither the Entry nor Exit condition is engaged.

> ##### Constructors

>     public WakeupOnSensorEntry(Bounds region)

> This constructor creates a WakeupOnSensorEntry object that informs the Java 3D scheduler to wake up the specified Behavior object whenever it detects a sensor within the specified `region` for the first time.

> ##### Methods

>     public Bounds getBounds()

> This method returns the Bounds object used in creating this WakeupCriterion.

>     public Sensor getTriggeringSensor()

> This method retrieves he Sensor object that caused the wakeup.

> #### 10.5.3.8 WakeupOnSensorExit

> This WakeupCriterion object specifies that Java 3D should awaken this behavior when any sensor, already marked as within the region, is no longer in that region.

> Note: This semantic guarantees that an Exit condition is engaged if its corresponding Entry condition was engaged.

> ##### Constructors

>     public WakeupOnSensorExit(Bounds region)

> This constructor creates a WakeupOnSensorExit object that informs the Java 3D scheduler to wake up the specified Behavior object the first time it detects that a sensor has left the specified `region`.

> ##### Methods

>     public Bounds getBounds()

> This method returns the Bounds object used in creating this WakeupCriterion.

>     public Sensor getTriggeringSensor()

> This method retrieves the Sensor object that caused the wakeup.

> #### 10.5.3.9 WakeupOnCollisionEntry

> This WakeupCriterion object specifies that Java 3D should awaken the WakeupOnCollisionEntry behavior when the specified object collides with any other object in the scene graph.

> ##### Constants

>     public static final int USE_GEOMETRY
>     public static final int USE_BOUNDS

> These constants specify whether collision against a Group, Shape, or Morph node is done using the actual geometry or whether the geometric bounds are used as an approximation.

> ##### Constructors

>     public WakeupOnCollisionEntry(SceneGraphPath armingPath)
>     public WakeupOnCollisionEntry(SceneGraphPath armingPath,
>            int  speedHint)
>     public WakeupOnCollisionEntry(Node armingNode)
>     public WakeupOnCollisionEntry(Node armingNode, int speedHint)
>     public WakeupOnCollisionEntry(Bounds armingBounds)

> These constructors create a WakeupOnCollisionEntry object that informs the Java 3D scheduler to wake up the specified Behavior object if the specified "armed" node's geometry or the specified "armed" bounds collides with any other object in the scene graph. The `speedHint` flag is either `USE_GEOMETRY` or `USE_BOUNDS`.

> ##### Methods

>     public SceneGraphPath getArmingPath()
>     public Bounds getArmingBounds()

> These methods return the "collidable" path or bounds object used in specifying the collision detection.

>     public SceneGraphPath getTriggeringPath()
>     public Bounds getTriggeringBounds()

> These methods return the path or bounds object that caused the collision.

> #### 10.5.3.10 WakeupOnCollisionExit

> This WakeupCriterion object specifies that Java 3D should awaken the WakeupOnCollisionExit behavior when the specified object no longer collides with any other object in the scene graph.

> ##### Constants

>     public static final int USE_GEOMETRY
>     public static final int USE_BOUNDS

> These constants specify whether collision against a Group, Shape, or Morph node is done using the actual geometry or whether the geometric bounds are used as an approximation.

> ##### Constructors

>     public WakeupOnCollisionExit(SceneGraphPath armingPath)
>     public WakeupOnCollisionExit(SceneGraphPath armingPath,
>            int  speedHint)
>     public WakeupOnCollisionExit(Node armingNode)
>     public WakeupOnCollisionExit(Node armingNode, int speedHint)
>     public WakeupOnCollisionExit(Bounds armingBounds)

> These constructors create a WakeupOnCollisionExit object that informs the Java 3D scheduler to wake up the specified Behavior object if the specified "armed" node's geometry or the specified "armed" bounds no longer collides with any other object in the scene graph. The `speedHint` flag is either `USE_GEOMETRY` or `USE_BOUNDS`.

> ##### Methods

>     public SceneGraphPath getArmingPath()
>     public Bounds getArmingBounds()

> These methods return the "collidable" path or bounds object used in specifying the collision detection.

>     public SceneGraphPath getTriggeringPath()
>     public Bounds getTriggeringBounds()

> These methods return the path or bounds object that caused the collision.

> #### 10.5.3.11 WakeupOnCollisionMovement

> This WakeupCriterion object specifies that Java 3D should awaken the WakeupOnCollisionMovement behavior when the specified object moves while in a state of collision with any other object in the scene graph.

> ##### Constants

>     public static final int USE_GEOMETRY
>     public static final int USE_BOUNDS

> These constants specify whether collision against a Group, Shape, or Morph node is done using the actual geometry or whether the geometric bounds are used as an approximation.

> ##### Constructors

>     public WakeupOnCollisionMovement(SceneGraphPath armingPath)
>     public WakeupOnCollisionMovement(SceneGraphPath armingPath,
>            int  speedHint)
>     public WakeupOnCollisionMovement(Node armingNode)
>     public WakeupOnCollisionMovement(Node armingNode, int speedHint)
>     public WakeupOnCollisionMovement(Bounds armingBounds)

> These constructors create a WakeupOnCollisionMovement object that informs the Java 3D scheduler to wake up the specified Behavior object if the specified node's geometry or the specified bounds collides with any other object in the scene graph. The `speedHint` flag is either `USE_GEOMETRY` or `USE_BOUNDS`.

> ##### Methods

>     public SceneGraphPath getArmingPath()
>     public Bounds getArmingBounds()

> These methods return the "collidable" path or bounds object used in specifying the collision detection.

>     public SceneGraphPath getTriggeringPath()
>     public Bounds getTriggeringBounds()

> These methods return the path or bounds object that caused the collision.

> #### 10.5.3.12 WakeupOnViewPlatformEntry

> This WakeupCriterion object specifies that Java 3D should awaken the WakeupOnViewPlatformEntry behavior when any ViewPlatform enters the specified region.

> Note: There can be situations in which a ViewPlatform may enter and then exit an armed region so rapidly that neither the Entry nor Exit condition is engaged.

> ##### Constructors

>     public WakeupOnViewPlatformEntry(Bounds region)

> This constructor creates a WakeupOnViewPlatformEntry object that informs the Java 3D scheduler to wake up the specified Behavior object whenever it detects a ViewPlatform center within the specified `region` for the first time.

> ##### Methods

>     public Bounds getBounds()

> This method returns the Bounds object used in creating this WakeupCriterion.

> #### 10.5.3.13 WakeupOnViewPlatformExit

> This WakeupCriterion object specifies that Java 3D should awaken the WakeupOnViewPlatformExit behavior when any ViewPlatform, already marked as within the region, is no longer in that region.

> Note: This semantic guarantees that an Exit condition gets engaged if its corresponding Entry condition was engaged.

> ##### Constructors

>     public WakeupOnViewPlatformExit(Bounds region)

> This constructor creates a WakeupOnViewPlatformExit object that informs the Java 3D scheduler to wake up the specified Behavior object the first time it detects that a ViewPlatform has left the specified `region`.

> ##### Methods

>     public Bounds getBounds()

> This method returns the Bounds object used in creating this WakeupCriterion.

> #### 10.5.3.14 WakeupOnTransformChange

> The WakeupOnTransformChange object specifies a wakeup when the transform within a specified TransformGroup changes.

> ##### Constructors

>     public WakeupOnTransformChange(TransformGroup node)

> This constructor creates a new WakeupOnTransformChange criterion.

> ##### Methods

>     public TransformGroup getTransformGroup()

> This method returns the TransformGroup node used in creating this WakeupCriterion.

> #### 10.5.3.15 WakeupAnd

> The WakeupAnd class specifies any number of wakeup conditions ANDed together. This WakeupCondition object specifies that Java 3D should awaken this Behavior when all of the WakeupCondition's constituent wakeup criteria become valid.

> ##### Constructors

>     public WakeupAnd(WakeupCriterion conditions[])

> This constructor creates a WakeupAnd object that informs the Java 3D scheduler to wake up this Behavior object when all the conditions specified in the array of WakeupCriterion objects have become valid.

> #### 10.5.3.16 WakeupOr

> The WakeupOr class specifies any number of wakeup conditions ORed together. This WakeupCondition object specifies that Java 3D should awaken this Behavior when any of the WakeupCondition's constituent wakeup criteria becomes valid.

> ##### Constructors

>     public WakeupOr(WakeupCriterion conditions[])

> This constructor creates a WakeupOr object that informs the Java 3D scheduler to wake up this Behavior object when any condition specified in the array of WakeupCriterion objects becomes valid.

> #### 10.5.3.17 WakeupAndOfOrs

> The WakeupAndOfOrs class specifies any number of OR wakeup conditions ANDed together. This WakeupCondition object specifies that Java 3D should awaken this Behavior when all of the WakeupCondition's constituent WakeupOr conditions become valid.

> ##### Constructors

>     public WakeupAndOfOrs(WakeupOr conditions[])

> This constructor creates a WakeupAndOfOrs object that informs the Java 3D scheduler to wake up this Behavior object when all of the WakeupOr conditions specified in the array of WakeupOr objects become valid.

> #### 10.5.3.18 WakeupOrOfAnds

> The WakeupOrOfAnds class specifies any number of AND wakeup conditions ORed together. This WakeupCondition object specifies that Java 3D should awaken this Behavior when any of the WakeupCondition's constituent Wakeup-And conditions becomes valid.

> ##### Constructors

>     public WakeupOrOfAnds(WakeupAnd conditions[])

> This constructor creates a WakeupOrOfAnds object that informs the Java 3D scheduler to wake up this Behavior object when any of the WakeupAnd conditions specified in the array of WakeupAnd objects becomes valid.

> ## 10.6 Interpolator Behaviors

> This section describes Java 3D's predefined Interpolator behaviors. They are called interpolators because they smoothly interpolate between the two extreme values that an interpolator can produce. Interpolators perform simple behavioral acts, yet they provide broad functionality.

> The Java 3D API provides interpolators for a number of functions: manipulating transforms within a TransformGroup, modifying the values of a Switch node, and modifying Material attributes such as color and transparency.

> These predefined Interpolator behaviors share the same mechanism for specifying and later for converting a temporal value into an alpha value. Interpolators consist of two portions: a generic portion that all interpolators share and a domain-specific portion.

> The generic portion maps time in milliseconds onto a value in the range [0.0, 1.0] inclusive. The domain-specific portion maps an alpha value in the range [0.0, 1.0] onto a value appropriate to the predefined behavior's range of outputs. An alpha value of 0.0 generates an interpolator's minimum value, an alpha value of 1.0 generates an interpolator's maximum value, and an alpha value somewhere in between generates a value proportionally in between the minimum and maximum values.

> ### 10.6.1 Mapping Time to Alpha

> Several parameters control the mapping of time onto an alpha value. That mapping is deterministic as long as its parameters do not change. Thus, two different interpolators with the same parameters will generate the same alpha value given the same time value. This means that two interpolators that do not communicate can still precisely coordinate their activities, even if they reside in different threads or even different processors-as long as those processors have consistent clocks.

> Figure 10-1 shows the components of an interpolator's time-to-alpha mapping. Time is represented on the horizontal axis. Alpha is represented on the vertical axis. As we move from left to right, we see the alpha value start at 0.0, rise to 1.0, and then decline back to 0.0 on the right-hand side.

> On the left-hand side, the trigger time defines when this interpolator's waveform begins in milliseconds. The region directly to the right of the trigger time, labeled Phase Delay, defines a time period where the waveform does not change. During phase delays alpha is either 0 or 1, depending on which region it precedes.

> Phase delays provide an important means for offsetting multiple interpolators from one another, especially where the interpolators have all the same parameters. The next four regions, labeled increasing, at 1, decreasing, and at 0, all specify durations for the corresponding values of alpha.

> Interpolators have a loop count that determines how many times to repeat the sequence of alpha increasing, alpha at 1, alpha decreasing, and alpha at 0; they also have associated mode flags that enable either the increasing or decreasing portions, or both, of the waveform.

> Figure 10-1 An Interpolator's Generic Time-to-Alpha Mapping Sequence

> Developers can use the loop count in conjunction with the mode flags to generate various kinds of actions. Specifying a loop count of 1 and enabling the mode flag for only the alpha-increasing and alpha-at-1 portion of the waveform, we would get the waveform shown in Figure 10-2.

> Figure 10-2 An Interpolator Set to a Loop Count of 1 with Mode Flags Set to Enable Only the Alpha-Increasing and Alpha-at-1 Portion of the Waveform

> In Figure 10-2, the alpha value is 0 before the combination of trigger time plus the phase delay duration. The alpha value changes from 0 to 1 over a specified interval of time, and thereafter the alpha value remains 1 (subject to the reprogramming of the interpolator's parameters). A possible use of a single alpha-increasing value might be to combine it with a rotation interpolator to program a door opening.

> Similarly, by specifying a loop count of 1 and a mode flag that enables only the alpha-decreasing and alpha-at-0 portion of the waveform, we would get the waveform shown in Figure 10-3.

> In Figure 10-3, the alpha value is 1 before the combination of trigger time plus the phase delay duration. The alpha value changes from 1 to 0 over a specified interval; thereafter the alpha value remains 0 (subject to the reprogramming of the interpolator's parameters). A possible use of a single -decreasing value might be to combine it with a rotation interpolator to program a door closing.

> Figure 10-3 An Interpolator Set to a Loop Count of 1 with Mode Flags Set to Enable Only the Alpha-Decreasing and Alpha-at-0 Portion of the Waveform

> We can combine both of the above waveforms by specifying a loop count of 1 and setting the mode flag to enable both the alpha-increasing and alpha-at-1 portion of the waveform as well as the alpha-decreasing and alpha-at-0 portion of the waveform. This combination would result in the waveform shown in Figure 10-4.

> Figure 10-4 An Interpolator Set to a Loop Count of 1 with Mode Flags Set to Enable All Portions of the Waveform

> In Figure 10-4, the alpha value is 0 before the combination of trigger time plus the phase delay duration. The alpha value changes from 0 to 1 over a specified period of time, remains at 1 for another specified period of time, then changes from 1 to 0 over a third specified period of time; thereafter the alpha value remains 0 (subject to the reprogramming of the interpolator's parameters). A possible use of an alpha-increasing value followed by an alpha-decreasing value might be to combine it with a rotation interpolator to program a door swinging open and then closing.

> By increasing the loop count, we can get repetitive behavior, such as a door swinging open and closed some number of times. At the extreme, we can specify a loop count of -1 (representing infinity).

> We can construct looped versions of the waveforms shown in Figure 10-2, Figure 10-3, and Figure 10-4. Figure 10-5 shows a looping interpolator with mode flags set to enable only the alpha-increasing and alpha-at-1 portion of the waveform.

> Figure 10-5 An Interpolator Set to Loop Infinitely and Mode Flags Set to Enable Only the Alpha-Increasing and Alpha-at-1 Portion of the Waveform

> In Figure 10-5, alpha goes from 0 to 1 over a fixed duration of time, stays at 1 for another fixed duration of time, and then repeats.

> Similarly, Figure 10-6 shows a looping interpolator with mode flags set to enable only the alpha-decreasing and alpha-at-0 portion of the waveform.

> Figure 10-6 An Interpolator Set to Loop Infinitely and Mode Flags Set to Enable Only the Alpha-Decreasing and Alpha-at-0 Portion of the Waveform

> Finally, Figure 10-7 shows a looping interpolator with both the increasing and decreasing portions of the waveform enabled.

> In all three cases shown by Figure 10-5, Figure 10-6, and Figure 10-7, we can compute the exact value of alpha at any point in time.

> Figure 10-7 An Interpolator Set to Loop Infinitely and Mode Flags Set to Enable All Portions of the Waveform

> Java 3D's preprogrammed behaviors permit other behaviors to change their parameters. When such a change occurs, the alpha value changes to match the state of the newly parameterized interpolator.

> ### 10.6.2 Acceleration of Alpha

> Commonly, developers want alpha to change slowly at first and then to speed up until the change in alpha reaches some appropriate rate. This is analogous to accelerating your car up to the speed limit-it does not start off immediately at the speed limit. Developers specify this "ease-in, ease-out" behavior through two additional parameters, the `increasingAlphaRampDuration` and the `decreasing-AlphaRampDuration`.

> Each of these parameters specifies a period within the increasing or decreasing alpha duration region during which the "change in alpha" is accelerated (until it reaches its maximum per-unit-of-time step size) and then symmetrically decelerated. Figure 10-8 shows three general examples of how the `increasingAlphaRampDuration` method can be used to modify the alpha waveform. A value of 0 for the increasing ramp duration implies that is not accelerated; it changes at a constant rate. A value of 0.5 or greater (clamped to 0.5) for this increasing ramp duration implies that the change in is accelerated during the first half of the period and then decelerated during the second half of the period. For a value of n that is less than 0.5, alpha is accelerated for duration n, held constant for duration (1.0 - 2n), then decelerated for duration n of the period.

> ### 10.6.3 The Alpha Class

> The Alpha node component object provides common methods for converting a time value into an alpha value (a value in the range 0.0 to 1.0). The Alpha object is effectively a function of time that generates alpha values in the range [0,1] when sampled: ft = [0,1]. The function ft and the characteristics of the Alpha object are determined by the following user-definable parameters:

> Figure 10-8 How an Alpha-Increasing Waveform Changes with Various Values of increasing-AlphaRampDuration

> - loopCount: Specifies the number of times to run this Alpha. A value of -1 specifies that the Alpha loops indefinitely.

> - triggerTime: Specifies the time in milliseconds since the start time that this object first triggers. If `startTime` + `triggerTime` is less than `currentTime`, the Alpha object is started as soon as possible by the system.

> - phaseDelayDuration: Specifies the number of milliseconds to wait after `triggerTime` before actually starting this Alpha.

> - mode: The mode can be set to INCREASING_ENABLE or DECREAS-ING_ENABLE or the ORed value of the two. INCREASING_ENABLE activates the increasing Alpha parameters described later. DECREAS-ING_ENABLE activates the decreasing Alpha parameters listed later.

> The increasing Alpha parameters are

> - increasingAlphaDuration: Specifies the time period during which Alpha goes from zero to one.

> - increasingAlphaRampDuration: Specifies the time period during which the Alpha step size increases at the beginning of the `increasingAlpha-Duration` and, correspondingly, decreases at the end of the `increasing--AlphaDuration`. This parameter is clamped to half of `increasing-AlphaDuration`. When this parameter is nonzero, one gets constant acceleration while it is in effect; constant positive acceleration at the beginning of the ramp and constant negative acceleration at the end of the ramp. If this parameter is zero, the effective velocity of the Alpha value is constant and the acceleration is zero (that is, linearly increasing alpha ramp).

> - alphaAtOneDuration: Specifies the time period that Alpha stays at one.

> The decreasing Alpha parameters are

> - decreasingAlphaDuration: Specifies the time period during which Alpha goes from one to zero.

> - decreasingAlphaRampDuration: Specifies the time period during which the Alpha step size increases at the beginning of the `decreasingAlphaDuration` and, correspondingly, decreases at the end of the `decreasingAlphaDuration`. This parameter is clamped to half of `decreas-ingAlpha-Duration`. When this parameter is nonzero, one gets constant acceleration while it is in effect-constant positive acceleration at the beginning of the ramp and constant negative acceleration at the end of the ramp. If this parameter is zero, the effective velocity of the Alpha value is constant and the acceleration is zero (that is, a linearly-decreasing alpha ramp).

> - alphaAtZeroDuration: Specifies the time period that Alpha stays at zero.

> ##### Constants

>     public static final int INCREASING_ENABLE
>     public static final int DECREASING_ENABLE

> These flags specify that this alpha's mode is to use the increasing or decreasing component of the alpha, respectively.

> ##### Constructors

>     public Alpha()

> Constructs an Alpha object with the following default parameters:

> Parameter | Default Value
> --- | ---
> loopCount | -1
> mode | INCREASING_ENABLE
> triggerTime | 0
> phaseDelayDuration | 0
> increasingAlphaDuration | 1000
> increasingAlphaRampDuration | 0
> alphaAtOneDuration | 0
> decreasingAlphaDuration | 0
> decreasingAlphaRampDuration | 0
> alphaAtZeroDuration | 0

>     public Alpha(int loopCount, long increasingAlphaDuration)
>            public Alpha(int loopCount, long triggerTime,
>            long  phaseDelayDuration, long increasingAlphaDuration,
>            long  increasingAlphaRampDuration, long  alphaAtOneDuration)
>     public Alpha(int loopCount, int mode, long triggerTime,
>            long  phaseDelayDuration, long increasingAlphaDuration,
>            long  increasingAlphaRampDuration, long  alphaAtOneDuration,
>            long  decreasingAlphaDuration,
>            long  decreasingAlphaRampDuration, long  alphaAtZeroDuration)

> Constructs a new Alpha object using the specified parameters to define the alpha phases for the object.

> ##### Methods

>     public float value()
>     public float value(long atTime)

> These methods return the alpha value (between 0.0 and 1.0 inclusive) based on the time-to-alpha parameters established for this interpolator. The first method returns the alpha for the current time. The second method returns the alpha for an arbitrary given time. If the alpha mapping has not started, the starting alpha value is returned. If the alpha mapping has completed, the ending alpha value is returned.

>     public void setStartTime(long startTime)
>     public long getStartTime()

> These methods set and retrieve this alpha's start time, the base for all relative time specifications. The default value of `startTime` is the system start time, defined to be a global time base representing the start of Java 3D execution.

>     public void setLoopCount(int loopCount)
>     public int getLoopCount()

> These methods set and retrieve this alpha's loop count.

>     public void setMode(int mode)
>     public int getMode()

> These methods set and retrieve this alpha's mode, which defines which of the alpha regions are active. The mode is one of the following values: `INCREASING_ENABLE`, `DECREASING_ENABLE`, or both (when both of these modes are ORed together).

> If the mode is `INCREASING_ENABLE`, the `increasingAlphaDuration`, `increasingAlphaRampDuration`, and `alphaAtOneDuration` are active. If the mode is `DECREASING_ENABLE`, the `decreasingAlphaDuration`, `decreasingAlphaRampDuration`, and `alphaAtZeroDuration` are active. If the mode is both constants ORed, all regions are active. Active regions are all preceded by the phase delay region.

>     public void setTriggerTime(long triggerTime)
>     public long getTriggerTime()

> These methods set and retrieve this alpha's trigger time.

>     public void setPhaseDelayDuration(long phaseDelayDuration)
>     public long getPhaseDelayDuration()

> These methods set and retrieve this alpha's phase delay duration.

>     public void setIncreasingAlphaDuration(long
>            increasingAlphaDuration)
>     public long getIncreasingAlphaDuration()

> These methods set and retrieve this alpha's `increasingAlphaDuration`.

>     public void setIncreasingAlphaRampDuration(long
>            increasingAlphaRampDuration)
>     public long getIncreasingAlphaRampDuration()

> These methods set and retrieve this alpha's `increasingAlphaRampDuration`.

>     public long getAlphaAtOneDuration()

> This method sets and retrieves this alpha's `alphaAtOneDuration`.

>     public void setDecreasingAlphaDuration(long
>            decreasingAlphaDuration)
>     public long getDecreasingAlphaDuration()

> These methods set and retrieve this alpha's `decreasingAlphaDuration`.

>     public void setDecreasingAlphaRampDuration(long
>            decreasingAlphaRampDuration)
>     public long getDecreasingAlphaRampDuration()

> These methods set and retrieve this alpha's `decreasingAlphaRampDuration`.

>     public long getAlphaAtZeroDuration()

> This method sets and retrieves this alpha's `alphaAtZeroDuration`.

>     public boolean finished()

> This method returns `true` if this Alpha object is past its activity window-that is, if it has finished all its looping activity. This method returns `false` if this Alpha object is still active.

> ### 10.6.4 The Interpolator Base Class

> Interpolator is an abstract behavior class from which several subclasses are derived. The base Interpolator class contains an Alpha object that provides the means for converting a time value (in milliseconds) into an alpha value in the range [0.0, 1.0] inclusive. Its subclasses map this alpha value into domain-specific values in their range.

> ##### Constants

>     protected WakeupCriterion defaultWakeupCriterion

> This is the default WakeupCondition for all interpolators. The `wakeupOn` method of Behavior, which takes a WakeupCondition as the method parameter, will need to be called at the end of the `processStimulus` method of any class that subclasses Interpolator. This is done with the following method call:

>     wakeupOn(defaultWakeupCriterion);

> ##### Constructors

> The Interpolator behavior class has the following constructors:

>     public Interpolator()

> Constructs and initializes a new Interpolator with a null alpha value.

>     public Interpolator(Alpha alpha)

> Constructs and initializes a new Interpolator with the specified alpha value. This constructor provides the common initialization code for all specializations of Interpolator.

> ##### Methods

>     public void setAlpha(Alpha alpha)
>     public Alpha getAlpha()

> These methods set and retrieve this interpolator's Alpha object. Setting it to `null` causes the Interpolator to stop running.

>     public void setEnable(boolean state)
>     public boolean getEnable()

> These methods set and retrieve this Interpolator's enabled state-the default is enabled.

>     public void initialize()

> This is the generic predefined interpolator `initialize` method. It schedules the behavior to awaken at the next frame.

> ### 10.6.5 PositionInterpolator Object

> The PositionInterpolator class extends Interpolator. It modifies the translational component of its target TransformGroup by linearly interpolating between a pair of specified positions (using the value generated by the specified Alpha object). The interpolated position is used to generate a translation transform along the local X-axis of this interpolator.

> ##### Constructors

> The PositionInterpolator object specifies the following constructors:

>     public PositionInterpolator(Alpha alpha, TransformGroup target)

> Constructs a trivial position interpolator with a specified target, an `axisOf-Translation` set to the identity transformation, a `startPosition` of 0.0, and an `endPosition` of 1.0 along the X-axis.

>     public PositionInterpolator(Alpha alpha, TransformGroup target,
>            Transform3D axisOfTranslation, float startPosition,
>            float  endPosition)

> Constructs and initializes a new PositionInterpolator that varies the target TransformGroup node's translational component (`startPosition` and `endPosition`). The `axisOfTranslation` parameter specifies the transform that defines the local coordinate system in which this interpolator operates. The translation is done along the X-axis of this local coordinate system.

> ##### Methods

> The PositionInterpolator object specifies the following methods:

>     public void setStartPosition(float position)
>     public float getStartPosition()

> These two methods set and get the Interpolator's start position.

>     public void setEndPosition(float position)
>     public float getEndPosition()

> These two methods set and get the Interpolator's end position.

>     public void setTarget(TransformGroup target)
>     public TransformGroup getTarget()

> These two methods set and get the Interpolator's target TransformGroup node.

>     public void setAxisOfTranslation(Transform3D axis)
>     public Transform3D getAxisOfTranslation()

> These two methods set and get the Interpolator's axis of translation.

>     public void processStimulus(Enumeration criteria)

> This method is invoked by the behavior scheduler every frame. It maps the alpha value that corresponds to the current time into a translation value, computes a transform based on this value, and updates the specified TransformGroup node with this new transform.

> ### 10.6.6 RotationInterpolator Object

> The RotationInterpolator class extends Interpolator. It modifies the rotational component of its target TransformGroup by linearly interpolating between a pair of specified angles (using the value generated by the specified Alpha object). The interpolated angle is used to generate a rotation transform about the local Y-axis of this interpolator.

> ##### Constructors

>     public RotationInterpolator(Alpha alpha, TransformGroup target)

> Constructs a trivial rotation interpolator with a specified `target`, an `axisOf-Rotation` set to identity, a minimum angle of 0 radians, and a maximum angle of 2 radians.

>     public RotationInterpolator(Alpha alpha, TransformGroup target,
>            Transform3D axisOfRotation, float minimumAngle,
>            float  maximumAngle)

> Constructs a new rotation interpolator that varies the target TransformGroup node's rotational component. The `minimumAngle` parameter is the starting angle, in radians; `maximumAngle` is the ending angle, in radians. The `axisOfRotation` parameter specifies the transform that defines the local coordinate system in which this interpolator operates. The rotation is done about the Y-axis of this local coordinate system.

> ##### Methods

>     public void setMinimumAngle(float angle)
>     public float getMinimumAngle()

> These two methods set and get the interpolator's minimum rotation angle, in radians.

>     public void setMaximumAngle(float angle)
>     public float getMaximumAngle()

> These two methods set and get the interpolator's maximum rotation angle, in radians.

>     public void setAxisOfRotation(Transform3D axis)
>     public Transform3D getAxisOfRotation()

> These two methods set and get the interpolator's axis of rotation.

>     public void setTarget(TransformGroup target)
>     public TransformGroup getTarget()

> These two methods set and get the interpolator's target TransformGroup node.

>     public void processStimulus(Enumeration criteria)

> This method is invoked by the behavior scheduler every frame. It maps the alpha value that corresponds to the current time into a rotation angle, computes a transform based on this angle, and updates the specified TransformGroup node with this new transform.

> ### 10.6.7 ColorInterpolator Object

> The ColorInterpolator class extends Interpolator. It modifies the diffuse color of its target material object by linearly interpolating between a pair of specified colors (using the value generated by the specified Alpha object).

> ##### Constructors

>     public ColorInterpolator(Alpha alpha, Material target)

> Constructs a trivial color interpolator with a specified target, a start color of black, and an end color of white.

>     public ColorInterpolator(Alpha alpha, Material target,
>            Color3f  startColor, color3f endColor)

> Constructs a new ColorInterpolator object that varies the diffuse color of the target material between two color values (`startColor` and `endColor`).

> ##### Methods

>     public void setStartColor(Color3f color)
>     public void getStartColor(Color3f color)

> These two methods set and get the interpolator's start color.

>     public void setEndColor(Color3f color)
>     public void getEndColor(Color3f color)

> These two methods set and get the interpolator's end color.

>     public void setTarget(Material target)
>     public Material getTarget()

> These two methods set and get the interpolator's target Material component object.

>     public void processStimulus(Enumeration criteria)

> This method is invoked by the behavior scheduler every frame. It maps the alpha value that corresponds to the current time into a color value and updates the diffuse color of the target Material object with this new color value.

> ### 10.6.8 ScaleInterpolator Object

> The ScaleInterpolator class extends Interpolator. It modifies the uniform scale component of its target TransformGroup by linearly interpolating between a pair of specified scale values (using the value generated by the specified Alpha object). The interpolated scale value is used to generate a scale transform in the local coordinate system of this interpolator.

> ##### Constructors

>     public ScaleInterpolator(Alpha alpha, TransformGroup target)

> Constructs a trivial scale interpolator that varies its target TransformGroup node between the two scale values, using the specified alpha, an identity matrix, a minimum scale of 0.1, and a maximum scale of 1.0.

>     public ScaleInterpolator(Alpha alpha, TransformGroup target,
>            Transform3D axisOfScale, float minimumScale,
>            float  maximumScale)

> Constructs a new ScaleInterpolator object that varies the target TransformGroup node's scale component between two scale values (`minimumScale` and `maximumScale`). The `axisOfScale` parameter specifies the transform that defines the local coordinate system in which this interpolator operates. The scale is done about the origin of this local coordinate system.

> ##### Methods

>     public void setMinimumScale(float scale)
>     public float getMinimumScale()

> These two methods set and get the interpolator's minimum scale.

>     public void setMaximumScale(float scale)
>     public float getMaximumScale()

> These two methods set and get the interpolator's maximum scale.

>     public void setAxisOfScale(Transform3D axis)
>     public Transform3D getAxisOfScale()

> These two methods set and get the interpolator's axis of scale.

>     public void setTarget(TransformGroup target)
>     public TransformGroup getTarget()

> These two methods set and get the interpolator's target TransformGroup node.

>     public void processStimulus(Enumeration criteria)

> This method is invoked by the behavior scheduler every frame. It maps the alpha value that corresponds to the current time into a scale value, computes a transform based on this value, and updates the specified TransformGroup node with this new transform.

> ### 10.6.9 SwitchValueInterpolator Object

> The SwitchValueInterpolator class extends Interpolator. It modifies the selected child of the target Switch node by linearly interpolating between a pair of specified child index values (using the value generated by the specified Alpha object).

> ##### Constructors

>     public SwitchValueInterpolator(Alpha alpha, Switch target)
>     public SwitchValueInterpolator(Alpha alpha, Switch target,
>            int  firstChildIndex, int lastChildIndex)

> Constructs a new SwitchValueInterpolator object that varies the target Switch node's child index between the two values provided (`firstChildIndex`, the index of the first children in the Switch node to select; and `lastChildIndex`, the index of the last children in the Switch node to select).

> ##### Methods

>     public void setFirstChildIndex(int firstIndex)
>     public int getFirstChildIndex()

> These two methods set and get the interpolator's first child index.

>     public void setLastChildIndex(int lastIndex)
>     public int getLastChildIndex()

> These two methods set and get the interpolator's last child index.

>     public void setTarget(Switch target)
>     public Switch getTarget()

> These two methods set and get the interpolator's target Switch node.

>     public void processStimulus(Enumeration criteria)

> This method is invoked by the behavior scheduler every frame. It maps the alpha value that corresponds to the current time into a child index value and updates the specified Switch node with this new child index value.

> ### 10.6.10 TransparencyInterpolator Object

> The TransparencyInterpolator class extends Interpolator. It modifies the transparency of its target TransparencyAttributes object by linearly interpolating between a pair of specified transparency values (using the value generated by the specified Alpha object).

> ##### Constructors

>     public TransparencyInterpolator(Alpha alpha,
>            TransparencyAttributes target)

> Constructs a trivial transparency interpolator with a specified target, a minimum transparency of 0.0 and a maximum transparency of 1.0.

>     public TransparencyInterpolator(Alpha alpha,
>            TransparencyAttributes target, float  minimumTransparency,
>            float maximumTransparency)

> Constructs a new TransparencyInterpolator object that varies the target material's transparency between the two transparency values (`minimumTransparency`, the starting transparency; and `maximumTransparency`, the ending transparency).

> ##### Methods

>     public void setMinimumTransparency(float transparency)
>     public float getMinimumTransparency()

> These two methods set and get the interpolator's minimum transparency.

>     public void setMaximumTransparency(float transparency)
>     public float getMaximumTransparency()

> These two methods set and get the interpolator's maximum transparency.

>     public void setTarget(TransparencyAttributes target)
>     public TransparencyAttributes getTarget()

> These two methods set and get the interpolator's target TransparencyAttributes component object.

>     public void processStimulus(Enumeration criteria)

> This method is invoked by the behavior scheduler every frame. It maps the alpha value that corresponds to the current time into a transparency value and updates the specified TransparencyAttributes object with this new transparency value.

> ### 10.6.11 PathInterpolator Object

> The PathInterpolator class extends Interpolator. This class defines the base class for all path interpolators. Subclasses have access to the `computePathInterpolation` method, which computes the `currentInterpolationValue` given the current time and alpha. The method also computes the `currentKnotIndex`, which is based on the `currentInterpolationValue`.

> The `currentInterpolationValue` is calculated by linearly interpolating among a series of predefined knot and orientation, pairs (using the value generated by the specified `Alpha` object). The last knot must have a value of 1.0; an intermediate knot with index k must have a value strictly greater than any knot with index less than k.

> ##### Constants

>     protected float currentInterpolationValue

> This value is the ratio between knot values indicated by the `currentKnotIndex` variable. So if a subclass wanted to interpolate between knot values, it would use the `currentKnotIndex` to get the bounding knots for the "real" value and then use the `currentInterpolationValue` to interpolate between the knots. To calculate this variable, a subclass needs to call the `computePathInterpolation` method from the subclass's `processStimulus` method. Then this variable will hold a valid value that can be used in further calculations by the subclass.

>     protected int currentKnotIndex

> This value is the index of the current base knot value, as determined by the alpha function. A subclass wishing to interpolate between bounding knots would use this index and the one following it and would use the `currentInterpolationValue` variable as the ratio between these indices. To calculate this variable, a subclass needs to call the `computePathInterpolation` method from the subclass's `processStimulus` method. Then this variable will hold a valid value that can be used in further calculations by the subclass.

> ##### Constructors

>     public PathInterpolator(Alpha alpha, float knots[])

> Constructs a new `PathInterpolator` object that varies the target TransformGroup node's transform.

> ##### Methods

>     public int getArrayLengths()

> This method retrieves the length of the knot and position arrays (which are the same length).

>     public void setKnot(int index, float knot)
>     public float getKnot(int index)

> These methods set and retrieve the knot at the specified index for this interpolator.

>     protected void setKnots(float[] knots)
>     public void getKnots(float[] knots)

> These methods set and retrieve an array of knot values. The set method replaces the existing array with the specified array. The get method copies the array of knots from this interpolator into the specified array. The array must be large enough to hold all of the knots.

>     protected void computePathInterpolation()

> This method computes the base knot index and interpolation value, given the current value of alpha and the knots[] array. If the index is 0 and there should be no interpolation, both the index variable and the interpolation variable are set to 0. Otherwise, `currentKnotIndex` is set to the lower index of the two bounding knot points, and the `currentInterpolationValue` variable is set to the ratio of the alpha value between these two bounding knot points.

> ### 10.6.12 PositionPathInterpolator Object

> The PositionPathInterpolator class extends PathInterpolator. It modifies the translational component of its target TransformGroup by linearly interpolating among a series of predefined knot/position pairs (using the value generated by the specified Alpha object). The interpolated position is used to generate a translation transform in the local coordinate system of this interpolator.

> The first knot must have a value of 0.0. The last knot must have a value of 1.0. An intermediate knot with index k must have a value strictly greater than any knot with index less than k.

> ##### Constructors

>     public PositionPathInterpolator(Alpha alpha,
>            TransformGroup  target, Transform3D axisOfTranslation,
>            float knots[], Point3f positions[])

> Constructs a new PositionPathInterpolator that varies the translation of the target TransformGroup's transform. The `axisOfTranslation` parameter specifies the transform that defines the local coordinate system in which this interpolator operates. The `knots` parameter specifies an array of knot values that specifies a spline. The `positions` parameter specifies an array of position values at the knots.

> ##### Methods

>     public void setPosition(int index, Point3f position)
>     public void getPosition(int index, Point3f position)

> These two methods set and get the interpolator's indexed position.

>     public void getPositions(Point3f[] positions)

> This method copies the array of position values from this interpolator into the specified array. The array must be large enough to hold all of the positions. The individual array elements must be allocated by the caller.

>     public void setAxisOfTranslation(Transform3D axis)
>     public Transform3D getAxisOfTranslation()

> These two methods set and get the interpolator's axis of translation.

>     public void setTarget(TransformGroup target)
>     public TransformGroup getTarget()

> These two methods set and get the interpolator's target TransformGroup object.

>     public void setPathArrays(float[] knots, Point3f[] positions)

> This method replaces the existing arrays of knot values and position values with the specified arrays. The arrays of knots and positions are copied into this interpolator object.

>     public void processStimulus(Enumeration criteria)

> This method is invoked by the behavior scheduler every frame. It maps the alpha value that corresponds to the current time into a translation value, computes a transform based on this value, and updates the specified TransformGroup node with this new transform.

> ### 10.6.13 RotPosPathInterpolator Object

> The RotPosPathInterpolator class extends PathInterpolator. It modifies the rotational and translational components of its target TransformGroup by linearly interpolating among a series of predefined knot/position and knot/orientation pairs (using the value generated by the specified Alpha object). The interpolated position and orientation are used to generate a transform in the local coordinate system of this interpolator.

> The first knot must have a value of 0.0. The last knot must have a value of 1.0. An intermediate knot with index k must have a value strictly greater than any knot with index less than k.

> ##### Constructors

>     public RotPosPathInterpolator(Alpha alpha, TransformGroup target,
>            Transform3D  axisOfRotPos, float knots[], Quat4f  quats[],
>            Point3f  positions[])

> This constructor constructs a new RotPosPathInterpolator that varies the rotation and translation of the target TransformGroup's transform. The `axisOfRotPos` parameter specifies the transform that defines the local coordinate system in which this interpolator operates. The `knots` parameter specifies an array of knot values that specifies a spline. The `quats` parameter specifies an array of quaternion values at the knots. The `positions` parameter specifies an array of position values at the knots.

> ##### Methods

>     public void setQuat(int index, Quat4f quat)
>     public void getQuat(int index, Quat4f quat)

> These two methods set and get the interpolator's indexed quaternion value.

>     public void getQuats(Quat4f[] quats)

> This method copies the array of quaternion values from this interpolator into the specified array. The array must be large enough to hold all of the quats. The individual array elements must be allocated by the caller.

>     public void setPosition(int index, Point3f position)
>     public void getPosition(int index, Point3f position)

> These two methods set and get the interpolator's indexed position.

>     public void getPositions(Point3f[] positions)

> This method copies the array of position values from this interpolator into the specified array. The array must be large enough to hold all of the positions. The individual array elements must be allocated by the caller.

>     public void setAxisOfRotPos(Transform3D axisOfRotPos)
>     public Transform3D getAxisOfRotPos()

> These two methods set and get the interpolator's axis of rotation and translation.

>     public void setTarget(TransformGroup target)
>     public TransformGroup getTarget()

> These two methods set and get the interpolator's target TransformGroup object.

>     public void setPathArrays(float[] knots, Quat4f[] quats,
>            Point3f[]  positions)

> This method replaces the existing arrays of knot values, quaternion values, and position values with the specified arrays. The arrays of knots, quats, and positions are copied into this interpolator object.

>     public void processStimulus(Enumeration criteria)

> This method is invoked by the behavior scheduler every frame. It maps the alpha value that corresponds to the current time into translation and rotation values, computes a transform based on these values, and updates the specified TransformGroup node with this new transform.

> ### 10.6.14 RotPosScalePathInterpolator Object

> The RotPosScalePathInterpolator class extends PathInterpolator. It varies the rotational, translational, and scale components of its target TransformGroup by linearly interpolating among a series of predefined knot/position, knot/orientation, and knot/scale pairs (using the value generated by the specified Alpha object). The interpolated position, orientation, and scale are used to generate a transform in the local coordinate system of this interpolator.

> The first knot must have a value of 0.0. The last knot must have a value of 1.0. An intermediate knot with index k must have a value strictly greater than any knot with index less than k.

> ##### Constructors

>     public RotPosScalePathInterpolator(Alpha alpha,
>            TransformGroup  target, Transform3D  axisOfRotPosScale,
>            float knots[], Quat4f  quats[], Point3f  positions[],
>            float  scales[])

> This constructor constructs a new RotPosScalePathInterpolator that varies the rotation, translation, and scale of the target TransformGroup's transform. The `axisOfRotPosScale` parameter specifies the transform that defines the local coordinate system in which this interpolator operates. The `knots` parameter specifies an array of knot values that specifies a spline. The `quats` parameter specifies an array of quaternion values at the knots. The `positions` parameter specifies an array of position values at the knots. The `scale` parameter specifies the scale component value.

> ##### Methods

>     public void setScale(int index, float scale)
>     public float getScale(int index)

> These two methods set and get the interpolator's indexed scale value.

>     public void getScales(float[] scales)

> This method copies the array of scale values from this interpolator into the specified array. The array must be large enough to hold all of the scales.

>     public void setQuat(int index, Quat4f quat)
>     public void getQuat(int index, Quat4f quat)

> These two methods set and get the interpolator's indexed quaternion value.

>     public void getQuats(Quat4f[] quats)

> This method copies the array of quaternion values from this interpolator into the specified array. The array must be large enough to hold all of the quats. The individual array elements must be allocated by the caller.

>     public void setPosition(int index, Point3f position)
>     public void getPosition(int index, Point3f position)

> These two methods set and get the interpolator's indexed position.

>     public void getPositions(Point3f[] positions)

> This method copies the array of position values from this interpolator into the specified array. The array must be large enough to hold all of the positions. The individual array elements must be allocated by the caller.

>     public void setAxisOfRotPosScale(Transform3D axisOfRotPosScale)
>     public Transform3D getAxisOfRotPosScale()

> These two methods set and get the interpolator's axis of rotation, translation, and scale.

>     public void setTarget(TransformGroup target)
>     public TransformGroup getTarget()

> These two methods set and get the interpolator's target TransformGroup object.

>     public void setPathArrays(float[] knots, Quat4f[] quats,
>            Point3f[]  positions, float[] scales)

> This method replaces the existing arrays of knot values, quaternion values, position values, and scale values with the specified arrays. The arrays of knots, quats, positions, and scales are copied into this interpolator object.

>     public void processStimulus(Enumeration criteria)

> This method is invoked by the behavior scheduler every frame. It maps the alpha value that corresponds to the current time into translation, rotation, and scale values; computes a transform based on these values; and updates the specified TransformGroup node with this new transform.

> ### 10.6.15 RotationPathInterpolator Object

> The RotationPathInterpolator class extends the PathInterpolator class. It varies the rotational component of its target TransformGroup by linearly interpolating among a series of predefined knot/orientation pairs (using the value generated by the specified Alpha object). The interpolated orientation is used to generate a rotation transform in the local coordinate system of this interpolator.

> The first knot must have a value of 0.0. The last knot must have a value of 1.0. An intermediate knot with index k must have a value strictly greater than any knot with index less than k.

> ##### Constructors

>     public RotationPathInterpolator(Alpha alpha,
>            TransformGroup  target, Transform3D  axisOfRotation,
>            float  knots[], Quat4f quats[])

> This constructor constructs a new RotationPathInterpolator object that varies the target TransformGroup node's transform. The `axisOfRotation` parameter specifies the transform that defines the local coordinate system in which this interpolator operates. The `knots` parameter specifies an array of knot values that specifies a spline. The `quats` parameter specifies an array of quaternion values at the knots.

> ##### Methods

>     public void setQuat(int index, Quat4f quat)
>     public void getQuat(int index, Quat4f quat)

> These two methods set and get the interpolator's indexed quaternion value.

>     public void setAxisOfRotation(Transform3D axisOfRotation)
>     public Transform3D getAxisOfRotation()

> These two methods set and get the interpolator's axis of rotation.

>     public void setTarget(TransformGroup target)
>     public TransformGroup getTarget()

> These two methods set and get the interpolator's target TransformGroup object.

>     public void setPathArrays(float[] knots, Quat4f[] quats)

> This method replaces the existing arrays of knot values and quaternion values with the specified arrays. The arrays of knots and quats are copied into this interpolator object.

>     public void getQuats(Quat4f[] quats)

> This method copies the array of quaternion values from this interpolator into the specified array. The array must be large enough to hold all of the quats. The individual array elements must be allocated by the caller.

>     public void processStimulus(Enumeration criteria)

> This method is invoked by the behavior scheduler every frame. It maps the alpha value that corresponds to the current time into a rotation angle, computes a transform based on this angle, and updates the specified TransformGroup node with this new transform.

> ## 10.7 Level-of-Detail Behaviors

> The LOD (Level of Detail) leaf node is an abstract behavior class that operates on a list of Switch group nodes to select one of the children of the Switch nodes. Specializations of the LOD abstract behavior node implement various level-of-detail policies.

> ### 10.7.1 LOD Object

> The LOD behavior node is an abstract class that is subclassed to implement selection among two or more levels of detail using an LOD selection criteria defined by the subclass.

> ##### Constructors

>     public LOD()

> Constructs and initializes a new LOD node.

> ##### Methods

> The LOD node class defines the following methods:

>     public void addSwitch(Switch switchNode)
>     public void setSwitch(Switch switchNode, int index)
>     public void insertSwitch(Switch switchNode, int index)
>     public void removeSwitch(int index)
>     public Switch getSwitch(int index)
>     public int numSwitches()

> The `addSwitch` method appends the specified Switch node to this LOD's list of switches. The `setSwitch` method replaces the specified Switch node with the Switch node provided. The `insertSwitch` method inserts the specified Switch node at the specified index. The `removeSwitch` method removes the Switch node at the specified index. The `getSwitch` method returns the Switch node specified by the index. The `numSwitches` method returns a count of this LOD's switches.

>     public Enumeration getAllSwitches()

> This method returns the Enumeration object of all switches.

> ### 10.7.2 DistanceLOD Object

> The DistanceLOD behavior node implements a distance-based LOD policy. It operates on a Switch group node to select one of the children of that Switch node based on the distance of this LOD node from the viewer. An array of n monotonically increasing distance values is specified, such that distances[0] is associated with the highest level of detail, and distances[n-1] is associated with the lowest level of detail. Based on the actual distance from the viewer to this DistanceLOD node, these n distance values [0, n-1] select from among n+1 levels of detail [0, n]. If d is the distance from the viewer to the LOD node, then the equation for determining which level of detail (child of the Switch node) is selected is

>   0, if d distances[0]

>   i, if distances[i-1] < d distances[i]

>   n, if d > distances[n-1]

> Both the position of this node and the array of LOD distances are defined in the local coordinate system of this node.

> ##### Constructors

>     public DistanceLOD()

> This constructor creates a DistanceLOD object with a single distance value set to 0.0 and is, therefore, not very useful.

>     public DistanceLOD(float distances[])
>     public DistanceLOD(float distances[], Point3f position)

> Construct and initialize a new DistanceLOD node. The `distances` parameter specifies a vector of doubles representing LOD cutoff distances. The `position` parameter specifies the position of this node in local coordinates. The default position is (0,0,0).

> ##### Methods

>     public void setPosition(Point3f position)
>     public void getPosition(Point3f position)

> These methods set and retrieve the `position` parameter for this DistanceLOD node. This position is specified in the local coordinates of this node, and is the position from which the distance to the viewer is computed.

>     public int numDistances()
>     public double getDistance(int whichDistance)
>     public void setDistance(int whichDistance, double distance)

> The `numDistances` method returns a count of the number of LOD distance cutoff parameters. The `getDistance` method returns a particular LOD cutoff distance. The `setDistance` method sets a particular LOD cutoff distance.

>     public void initialize()

> This method sets up the initial wakeup criteria.

>     public void processStimulus(Enumeration criteria)

> This method computes the appropriate level of detail.

> ## 10.8 Billboard Behavior

> The Billboard behavior node operates on the TransformGroup node to cause the local +z axis of the TransformGroup to point at the viewer's eye position. This is done regardless of the transforms above the specified TransformGroup node in the scene graph.

> Billboard nodes provide the most benefit for complex, roughly symmetric objects. A typical use might consist of a quadrilateral that contains a texture map of a tree.

> The Billboard node is similar in functionality to the OrientedShape3D node. See also Section 6.2.1, "OrientedShape3D Node."

> ##### Constants

> The Billboard class adds the following new constants:

>     public static final int ROTATE_ABOUT_AXIS

> Specifies that rotation should be about the specified axis.

>     public static final int ROTATE_ABOUT_POINT

> Specifies that rotation should be about the specified point and that the children's y-axis should match the ViewPlatform's Y-axis.

> ##### Constructors

> The Billboard class specifies the following constructors:

>     public Billboard()

> Constructs a Billboard node with the following default parameters:

> Parameter | Default Value
> --- | ---
> alignmentMode | ROTATE_ABOUT_AXIS
> alignmentAxis | y-axis (0,1,0)
> rotationPoint | (0,0,1)
> target transform group | null

>     public Billboard(TransformGroup tg)

> Constructs a Billboard node with default parameters that operates on the specified TransformGroup node. The default alignment mode is `ROTATE_ABOUT_AXIS` rotation with the axis pointing along the y-axis.

>     public Billboard(TransformGroup tg, int mode, Vector3f axis)
>     public Billboard(TransformGroup tg, int mode, Point3f point)

> The first constructor constructs a Billboard behavior node with default parameters that operates on the specified target `TransformGroup` node. The default alignment mode is `ROTATE_ABOUT_AXIS`, with the axis along the Y-axis. The next two constructors construct a Billboard behavior node with the specified axis and mode that operate on the specified TransformGroup node. The `axis` parameter specifies the ray about which the billboard rotates. The `point` parameter specifies the position about which the billboard rotates. The `mode` parameter is the alignment mode and is either `ROTATE_ABOUT_AXIS` or `ROTATE_ABOUT_POINT`.

> ##### Methods

> The Billboard class defines the following methods:

>     public void setAlignmentMode(int mode)
>     public int getAlignmentMode()

> These methods, if enabled by the appropriate flag, permit an application to either retrieve or set the Billboard node's alignment mode, one of `ROTATE_ABOUT_AXIS` or `ROTATE_ABOUT_POINT`.

>     public void setAlignmentAxis(Vector3f axis)
>     public void setAlignmentAxis(float x, float y, float z)
>     public void getAlignmentAxis(Vector3f axis)

> These methods, if enabled by the appropriate flag, permit an application to set or retrieve the Billboard node's alignment axis.

>     public void setTarget(TransformGroup tg)
>     public TransformGroup getTarget()

> These methods set or retrieve the target TransformGroup node for this Billboard object.

>     public void setRotationPoint(float x, float y, float z)
>     public void setRotationPoint(Point3f point)
>     public void getRotationPoint(Point3f point)

> The first two methods set the rotation point. The third method gets the rotation point and sets the parameter to this value.

>     public void initialize()

> This method sets up the initial wakeup criteria.

>     public void processStimulus(Enumeration criteria)

> This method computes the appropriate transform.

The Java 3D API Specification |

##### Copyright © 2000, Sun Microsystems, Inc. All rights reserved.