![]() | ![]() | ![]() |
|
Interpolators© Justin Couch 1999Previously we mentioned the use of interpolators as behaviours. Despite their apparently simple nature, they are quite sophisticated in what they can provide the user. As mentioned earlier, an interpolator takes an input, usually time based, and produces an output appropriate to the type of interpolator. When producing time based interpolated routines, you can wire up several of these in parallel to produce a very interesting and complex output.
Interpolator BasicsSay we have a path as indicated in Figure 5. This path is the real path that we need to travel in a car to get from point A to point B. Most of the time we need to travel in straight lines, only when we get to a corner will the direction change. We need to build an application that will show that output to a user.
![]() Figure 5: A path that we want to travel One option in our application is to set up a behaviour that wakes on every frame. For that frame it looks up the next position based on what frame number we are at and moves the view to that position. While this runs really nicely on your machine, the users complain that it is really jerky or runs in contravention to the laws of physics. Apart from that, your server gets overloaded from the amount of calculation it needs to do to present every single point. Obviously this is not really ideal. The users are experiencing this behaviour because you based everything on a per-frame basis. Every machine has different frame rates simply because of different CPU speeds, amount of memory or video card. An easier solution to the problem is to just provide the corner values and let "the system" work out all the positions in between - that is what an interpolator does. The basic interpolator is just a set of key/value pairs. So if we strip all the map part from the image we are left with Figure 11-6 a series of known positions and the time it should take us to travel between each position.
![]() Figure 6: The path from figure 5 stripped to the important waypoints That leaves us with a series of values:
When the interpolator is given a key that is between T1 and T2 it will produce the corresponding value proportionally distant between X1,Y1 and X2, Y2.How it determines what that output value is, is dependent on the type of interpolator. For positional information it is just a simple linear interpolation of the values. However, for color interpolation there are a number of different color spaces that may be used to interpolate between any two color values. For example, two RGB color values may use either RGB space or HSV space - each of which result in totally different output color values for the same key. Time and AlphaIn Java3D parlance, the key is called an Alpha and is encapsulated in its own class. Alpha values are used as the glue between the system time and the key values for interpolators. With theAlpha class, you can control exactly how to interpret time and
control the output anywhere from a one-shot animation to continually looping
value.
The
On first contact the
![]() Figure 7: Diagrammatic representation of the field values of the Alpha class.
Using InterpolatorsFor most applications, there will be little need to specify all of these values. Typically you will only want to define the trigger time, whether or not to loop and the increasing alpha duration. To illustrate in code what you need to do to get an interpolator going, we’ll make our geometry example from the previous chapter spin.
The first step in using any interpolator is making sure that there is an
instance of the object that you need to manipulate already created. When you
look at the // add some geometry GeometryTest geom = new GeometryTest(); TransformGroup tg = new TransformGroup(); tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); tg.addChild(geom); // Create the behaviour universe.addWorldObject(tg);Notice that we’ve also had to enable the capability to write the transform. This should seem fairly obvious because we need to be constantly changing the transform to make the object rotate.
Next we need to build the behaviour and all the supporting classes. The
default implementation of the rotation interpolator is to circle between 0
and 2pi meaning that we don’t need to do anything special. Since this is the
case, the public BehaviourTest(TransformGroup tg) { Alpha alpha = new Alpha(-1, 5000); RotationInterpolator rotator = new RotationInterpolator(alpha, tg); tg.addChild(rotator); }The constructor used in the Alpha class creates the basic
saw-tooth shaped output that we discussed in the previous section. The value
of -1 for the first argument says to loop forever, while 5000 indicates that
a period of 5 seconds should be used (remember the values are in
milliseconds). If you just compiled and ran this code you would notice that
nothing happens. Remember earlier in the chapter the discussions about
scheduling bounds? Well, the default implementation provides no bounds, so
we need to explicitly create them. For the purposes of this exercise, a
spherical bound of radius 100 should do us quite well. The following code is
then inserted just before the last line of the previous example:
Point3d origin = new Point3d(0, 0, 0); Transform3D axis = new Transform3D(); BoundingSphere bounds = new BoundingSphere(origin, 100.0); rotator.setSchedulingBounds(bounds); Standard InterpolatorsMoving positions is not the only sort of interpolator that you can define:
|
|