The Source for Java Technology Collaboration
User: Password:
Register | Login help    

Search

Online Books:
java.net on MarkMail:


Been There, Scene That: Part 2

Posted by chet on January 8, 2008 at 4:17 PM PST

(This is the conclusion of a two-parter that was begun last week and split in half for no particularly good reason. If you didn't read last week's entry yet, please do. I'll wait. ... Now, are you ready? Then let's get started.)

New Stuff

Most of the changes between TimingFramework and the scene graph animation library are tweaks on existing functionality, as described above. But there is also new functionality in the scene graph animation engine. Some of it is functionality that we have wanted in the TimingFramework for some time - we just happened to get around to it in this animation engine first.

Timeline

The Timeline class is probably the biggest new thing since the Timing Framework. It adds a crucial missing piece of functionality from the original library: the ability to group animations, schedule them in a coordinated fashion, and use one, single heartbeat for all animations.

"Nice Grouping!"

The previous approach of daisy-chaining animations one-by-one with TimingTrigger was quite useful for individual sequences of animations. And the new addBeginAnimation()/addEndAnimation() methods of Clip enhance this capability significantly. But it's still not what you want for larger systems with entire groups of animations that need to be coordinated. Instead, you want some way to create groups of animations that operate on a single timeline relative to each other and then schedule that group appropriately with other animations or other animation groups. This functionality makes it much easier to build up more complex and interdependent models of animations.

Timeline enables this capability by allowing you to schedule animations on a given Timeline relative to when the Timeline itself starts. So, for example, if you want to fire off animations a, b, and c 100, 200, and 300 ms after some even occurs, then you can schedule these animations on a single Timeline and start the Timeline when that event occurs:

            // Create the animation group
            Timeline timeline = new Timeline();
            timeline.schedule(a, 100);
            timeline.schedule(b, 200);
            timeline.schedule(c, 300);
            
            // Later, when the event occurs
            timeline.start();

"Two Hearts Beat as One"

One of the biggest recurring constraints that I ran up against with the TimingFramework was the fact that each Animator started its own Swing Timer by default. You could change this behavior, with the late-addition class TimingSource, but it wasn't a convenient way to get what you really wanted: a single timer for the whole system. You could also get a single-timer kind of behavior by adding multiple TimingTargets to a single Animator, but this approach only works easily in situations where you want similar timing and behavior characteristics from all of these targets; for example, animations of different durations or interpolation are difficult to synchronize in this way.

What the system really needed was a single timing source that sent a heartbeat pulse to all animations. Each animation could then turn that pulse into an appropriate timing fraction, just as Animator does with its internal Swing Timer events. But there are a couple of excellent reasons why the single-pulse-generator model is superior to the multiple-Swing-Timer approach:

  • Synchronized animations: If you have several animations in the system that are affecting the GUI, or are otherwise related in some way, you probably want them all to receive their timing events at the same time instead of at slightly different times because their internal Timers are kicking off at different intervals. Coordinating rendering changes in the single GUI display is a Good Thing; each element animating separately from everything else around it could contribute to a more chaotic user experience.
  • Resolution and frame rate: Anyone that worked through the gorey details in the Resolution section of chapter 12 of Filthy Rich Clients (or anyone that's just worked closely with the Swing Timer) knows that the performance of that Timer is often gated by constraints on the native platform. For example, on Windows XP, the Swing Timer typically has an inter-event rate of about 16 milliseconds. This is because that's the highest rate achievable by the native low-resolution timer upon which the Swing Timer depends (through its use of Object.wait()). This problem is compounded when there are several Timers firing off at the same time, because the timing events are all gated by that underlying wait() resolution, and cannot actually process the wait()'s in parallel.
    For example, say you have one Animator that you'd like to set up with a resolution of 10 ms. On Windows XP, you'd actually get timing events at a resolution of 16 ms instead. Now, suppose you create a second Animator, also with a resolution of 10 ms. Since the underlying Swing Timer processes the timing events one by one, and since the gating resolution of the timer is what it is, you'll actually end up with an effective resolution of 32 ms for each of these Animators.
    Now consider the model of the new animation engine, where there is just one single underlying timer running, sending out timing pulses to all animations in the system. This is more like the multiple-TimingTargets-per-Animator model where the only gating factor in resolution is that of the core timer itself, not how many Animators are waiting for the timing events.

Both of these capabilities of Timeline, grouping and the system-wide heartbeat, are managed through the various schedule() methods of Timeline. You schedule an animation to run with some offset from the beginning of a Timeline, and the Timeline ensures that that animation will start when it needs to and thereafter receive the master heartbeat events from the system. You can schedule other animations all on that same Timeline or on other Timelines and then schedule the Timelines themselves to start when appropriate.

            Timeline t1 = new Timeline();
            // ... schedule animations on Timeline t1 ...
            
            Timeline t2 = new Timeline();
            // ... schedule animations on Timeline t2 ...
            
            // Timeline t3 = new Timeline();
            // schedule t1 to start 100 ms after t3 starts
            t3.schedule(t1, 100);
            // schedule t2 to start 200 ms after g3 starts
            t3.schedule(t2, 200);
            // start t3
            t3.start();            

An important point to note here is that Timelines and Clips may both be scheduled on a Timeline. The schedule() methods actually take an Animation parameter, where Animation is a superclass of both Clip and Timeline. So a Timeline itself can be started relative to some point in another Timeline. In this way, we can create hierarchical groups of animations that are automatically triggered according to how we scheduled them together.

MotionPath

One constraint of the TimingFramework is that while time could be interpolated non-linearly (using a non-linear Interpolator object), space was always interpolated linearly. For example, if you set up an animation between points (x0, y0) and (x1, y1), then the system would interpolate intermediate (x, y) points linearly between these points; all points calculated by the system (by the old Evaluator class) would lie along a straight line drawn between the two endpoints.

The new MotionPath class makes it possible to create keyframes, and an Evaluator to interpolate between them, for curved paths.

What Now? Whither TimingFramework?

A logical question to ask now is, what about the Timing Framework? Is there a future in that project? Or should I start using the scene graph animation library instead?

I think the answer to these questions is still being figured out (since the scene graph library itself is still very much in-development), but here are a couple of reasonable ways to think about it, depending on your timeframe:

Short-term

The TimingFramework is in good shape in general. There was a reason that I declared it 1.0 (I didn't just randomly decide to add .44 to the previous release numbered 0.56). So please continue to use it as you see fit in your work for now. There are some minor issues that crop up occasionally that should probably be addressed in that library (although I admit I have been a bit preoccupied on Scene Graph and other things for a while and haven't been as responsive to issues as I'd like).

Scene Graph animation, on the other hand, is very much in flux right now. We're reasonably happy with the functionality of the library, but I wouldn't be shocked to see some more refactoring take place as we continue working on the Scene Graph project in general. So while I encourage you to take a look at it and play around with it, I wouldn't bet on the current implementation of it quite yet.

Long-term

I think (and this is where it gets fuzzy, because we're a bit busy focusing on the short-term right now and just trying to finish up the Scene Graph library in general) that the scene graph animation engine, or something very like it, will probably be the single library for animation eventually. It just doesn't make sense to have two such libraries, at least not coming out of the same group at Sun and not when one is essentially a subset of the other. When we get there and what the eventual, single library looks like when we're there is still a mystery. But long term, I see these libraries converging, and probably looking more like the Scene Graph version than Timing Framework.

But in the meantime, please use the Timing Framework while you investigate and starting playing with the Scene Graph animation engine. Send us feedback on what we could improve to make sure that the library we eventually end up with supports what you need from it.

By the Way

With all of this power to do cool, whizzy animations in Desktop Java applications, I'm thinking that "Scene Graph" isn't really a good enough name. Here's a possible alternative that I'm proposing, as of now:

Obscene

But it still feels like something's missing. Maybe it's just not graphic enough.

Related Topics >> Java Desktop      
Comments
Comments are listed in date ascending order (oldest first)

I want to thank you for coming up with this integrated framework. Btw, really smart move to create this outside of the JDK process. Could you imagine the (good) refactoring that you're making in public jdk classes? If only swing text was a external package...

Timeline is very useful. for my previous project, I wrote a wrapper class around Animator, called it Animator2, which links one Animator to other with specified time. I started using this new API in my application.

Are there any plans to address garbage collection pauses? A GC pause in the middle of a smooth animation can be very noticeable and cause the animation to look jerky.

spiff: We're still working on performance (including GC issues), along with a host of other issues; we're clearly still mid-development with this project. vdaburon: Apparently my joke mis-fired; I wasn't actually proposing a name change. The project name will stay the same fascinating, clever, and unique name that it is now: Scene Graph.

Hello, Obscene name is not a good idea for google search. You will find some "specials" web sites ... I suggest : 1) Scenatime 2) Anitime Vincent D.