13.3.5 Change detection
Another low-level capability that is useful for UI work is change detection, which
includes both spatial and nonspatial changes in target objects. External and internal
geometry changes are needed for many of the visualization techniques. Nonspatial
changes, such as appearance, the addition or removal of child components, or even
application-defined changes such as selection and mouseover, are useful in coordinating
object specification, configuration, and interaction states throughout the application.
Detection of changes is also useful in synchronizing user and programmatic-initiated
changes in the scene with renderer updates to the view display image.
Spatial changes
Detection of external geometry changes is a key aspect of the world overlay, display
facing, and constant size visualization techniques. These techniques generally require
immediate knowledge of any view and target object position and orientation changes.
Collision movement detection, discussed above, is an example of continuous external
geometry change detection: Whenever a triggering object moves— translates or
rotates— its external motion would be reported. As discussed earlier for spatial transforms,
in Java 3D, external geometry changes are specified and reported through
Transform3D objects. You may also remember that picking and collision results are
provided in the form of SceneGraphPath objects. The API designers had the fore-thought
to include the local-to-vworld transform of the target object as part of the
SceneGraphPath class, which is obtained with the getTransform method.
Although many of the behavior criteria detect discrete movement, such as collision
entry, the only one, other than collision movement, that detects continuous
motion is WakeupOnTransformChange. Given the problems with collision movement
detection and the collision model in general, you might think that it would be
a perfect alternative. Unfortunately, this criterion detects only geometry changes that
are local to its target TransformGroup object, specifically any changes to its
Transform3D component object. Such changes affect only the spatial geometry of its
child nodes as a whole, which are external to the children but internal to the target
group. Although such local motion detection is useful for certain situations, movement
of the transform group relative to the world space, as expressed by its local-to-Vworld
transform, is what is needed for the visualization techniques.
Although not much help in general purpose spatial change detection, Java 3D
provides a few behavior subclasses that incorporate change detection of external view
geometry, such as Billboard and LOD (level-of-detail). Keep in mind that if you are trying
to use such view dependent behaviors in a multi-view application that they will
work correctly only with a single designated view. The next release of Java 3D promises
to address this shortcoming. So, what does the framework do for general purpose spatial
change detection? The next section describes how to handle changes that are not
specifically covered by the API, as a developer's means of last resort.
Nonspatial changes
Even if external geometry changes could be correctly detected, the visualization
techniques also require internal geometry change detection. They specifically need
to be notified of changes to the internal state of the view, display, and screen spaces,
which include such parameters as display size, field-of-view, view and display scale
factors, and screen resolution. Some of these could be handled as AWT events, such
as display window size, but there is no specific way to handle the other changes. The
same goes for nongeometric changes, such as an object's appearance, constituent
members, and interaction state. To accommodate generic change detection and
notification, Java 3D provides a scheme for manually posting events to behaviors. To
use it, the application would explicitly detect a change, such as when the user inter-acts
with a virtual control or the application programmatically generates a change;
and post that change, such as a change in field-of-view, to interested target behaviors,
such as a visualization technique.
Behavior posting is handled through the WakeupOnBehaviorPost criterion,
which is constructed with a source Behavior object and an arbitrary post ID. When the
target behavior receives a post from the specified source behavior and/ or with the specified
post ID, it fires. A post is sent with the Behavior. postId method. Although
the assumption is that a post will be generated only by another behavior, situations can
arise outside of the behavior model that require a post, such as in response to a direct
AWT event. For such cases, a static version of the post method would be useful.
Unfortunately, there is a serious bug in behavior posting (confirmed by Sun) that
allows the target behavior to fire only once, with any subsequent postings to it being
ignored. This factor eliminated the final hope for using behaviors in the framework.
As an alternative, a nonbehavior form of posting had to be developed for the frame-work,
which is embodied in the j3dui. visualize. ChangePoster class. These and other
aspects of the framework are discussed in more detail in the next part of the book.
Update synchronization
Any time a visual change occurs to the scene graph or to the state of one of its nodes,
the change must be reflected in the view display. For this to happen, the Java 3D renderer,
which converts the 3D model represented by the scene graph into a 2D image in
the view display, must be notified of the change so that it can re-render the display.
Coupled with rendering update is the update to the scene graph itself. For all practical
purposes, in Java 3D, change notification to the renderer and commitment of changes
in the scene graph occur automatically; you as designer have no control over them.
The implications for change detection might seem subtle but the consequences
can be dramatic. For example, if the user turns a virtual knob on the display to rotate
the view of the scene, the following events would have to occur: The mouse drag
would be detected and a corresponding change to a transform group above the view
in the scene graph would be made. As a result of a scene graph node being changed,
the renderer would be notified automatically to update the display image. When the
image updates, the handling of the original event stimulus— the drag— is completed.
So far so good; but, what if you are using some visualization technique that depends
on knowing where the view is at all times, such as world overlay?
Expanding on the previous example, when the view's transform group changes,
the world overlay handler must be notified that the view's external geometry is changing.
When it receives this change notification, it goes to the view object in the scene
graph and gets its local-to-Vworld spatial transform, which the overlay handler in turn
uses to update the overlay position of its target object. Java 3D's update model is such
that, when a spatial transform is changed, even though the new state can be read back
immediately, it is not actually committed in the scene graph until the renderer starts
its display update. This means that when the overlay handler goes to get the view's
local-to-Vworld transform, the wrong value is returned. This is because the view
movement won't be committed until all scene graph changes are completed and the
renderer update begins.
The bottom line is that secondary event handlers that query the scene graph
state, such as world overlay, could be working with old information. Any changes
they make to the scene graph will appear out of sync with the rest of the display
update— and the overlaid object will appear in the wrong place. There is no work-around
for this problem, and its effects can be seen plainly in the WorldOverlaying
example in section 21. 2.4.
Update synchronization can be a hard problem to identify, especially because it
is only exposed in applications that are pushing the envelope, like the 3D techniques
described in this book. (I have always found it amusing that UI techniques are generally
not recognized as pushing the implementation envelope, but they do because they
are so intimately tied to the platform's event handling and nongeometric performance.)
It can be an even harder problem to solve, especially if you are also trying to
avoid event loops, which would be an even worse problem than out-of-date scene
graph information. Many graphics platforms have tried to tackle this problem and its
subtleties, and most have failed, Java 3D included. The next release of Java 3D promises
to fix this problem. As the saying goes, hope for the best but prepare for the worst.
New on the Java Boutique:
New Review:
Time Management Made Easy with the Quartz Enterprise Job Scheduler
Why not just use the Java timer API? This open source scheduling
API boasts simplicity, ease-of-integration, a well-rounded feature
set, and it's free!
New Applet:
Reverse Complement
Reverse Complement is a simple applet that converts DNA or RNA
sequences into three useful formats.
Elsewhere on internet.com:
WebDeveloper Java
Lots of Java information on webdeveloper.com
WDVL Java
Thorough Java resource at the Web Developer's Virtual Library.
ScriptSearch Java
Hundreds of free Java code files to download.
jGuru: Your View of the Java Universe
Customizable portal with online training, FAQs, regular news updates, and tutorials.