By no stretch of the animation
August 8, 2000
by Frank Di Luzio
Imagine you're being briefed by the client for a stand-alone interactive presentation at a trade show. The client wants two animations. For the first, she wants many layers of transparent images gliding past one another, including drop shadows. You nod in agreement, because Director can handle transparency, movement and sound. A second animation will be rendered using a 3D program. You agree on using 800x600 pixels for the stage size.
At the studio, Director is doing a decent job pushing around all those layers for the first animation. The only problem is maintaining a constant frame rate, because the number of sprites on stage is continuously changing. You're not too happy about having to drop the frame rate to 10 in order to keep the animation speed constant. In the meantime, the rendered images from the 3D program are complete. You receive a 56 (800x600 pixel) TIFF sequence that you import in Director and place in the score chronologically. But after saving and opening the file again, you realize Director doesn't play the sequence fast enough. By this time, you're already busy thinking about how to achieve better performance.
Assuming you had enough RAM, Director would have played the sequence of 3D renderings in the second animation quickly on the second try, because at that point the images were fully loaded in memory. However, the first animation, with its many layers of images gliding past one another, didn't show any noticeable improvement. This indicates that the most obvious way to improve the second animation's performance would be to do a preload.
If you're lucky, you're going to use a powerful computer to handle all this. But what do you do when the computer is not so powerful? In this article, I will lead you through the steps I took to maintain the frame rate without degrading the original image. I'll start with some preload techniques.
Preloading
Loading the TIFF sequence into RAM will result in the fastest playback speed possible. But this sequence of 56 800x600 32 bit TIFFs would require over 100MB. At 16 bit it reduces by half; 8 bit reduces by half again, but the image quality just doesn't cut it. If the image still looks good in 16 bit, that can help tremendously. In fact, fast machines will play the 16 bit sequence with no preload just as fast as a preloaded 32 bit version. But in some cases, the 16 bit image isn't good enough.
The idleLoadMode
The basic idea here is to preload media in the background without interrupting the flow of interactivity. The script below was used to preload the 56-frame sequence of 32 bit 800x600 pixel images while a couple of sprites moved across the screen diagonally from corner to corner. Their movement was not at all affected by the loading process.
on exitFrame me
the idleLoadMode = 3
the idleHandlerPeriod = 2
the idleReadChunkSize = 2000 * 1024
preload 100,155
the idleLoadTag = 10
end
The idleLoadTag is a method of identifying the preload to check if it's complete at some later point.
if idleLoadDone(10) then gLoaded = TRUE
Although this script does preload frames 100 to 155, the media for those frames is in a compressed form, which still needs to be decompressed. In cases where the CD-ROM speed is slow, this kind of preloading would indeed be a major improvement. However, due to larger compression ratios and faster CD-ROM read times, decompression may become the time-consuming element. Therefore, this kind of preload doesn't necessarily increase speed if the media is coming from a hard drive, as in this case. Using this script, the sequence played back at the same speed that it did without any preload method, since the decompressing of the media caused the slow playback in both cases.
The idleReadChunkSize value has a tremendous impact on how long the entire preload process needs. The current value is set slightly higher than the individual members' size of 1.8MB, since the media was on a hard drive and could load quickly. You'll need to experiment if you want to use higher rates than the default value of 32KB when loading media from a CD-ROM. In this case, the result of using the default value was that the diagonally-moving sprite animation repeated eight times, while it repeated only three times with the higher idleReadChunkSize.
A complete preload with decompression can be achieved by setting the idleLoadMode to 0 (zero). This causes the computer to do nothing else but preload, and makes checking if the media is loaded and other settings unnecessary. In this scenario, the moving sprite animation stopped completely until the preload was completed; the animation was fast.
Another method of loading and decompressing simultaneously can be achieved by placing the bitmap sequence in the score and moving it offstage. This method will maintain interactivity, but lower the maximum frame rate.
Please refer to the Lingo Dictionary for more detailed information about the individual lines of code.
RAM: Good to the last byte
At this point, the animation is fast enough, and a reasonable amount of interactivity has been maintained. But stuffing 100 MB into RAM is pretty obnoxious, especially for a sequence that lasts only seconds. Besides, Director needs RAM for other things. Director handles the memory management by default, and it will unload media you just preloaded when it runs out of memory. In order to avoid that, a leaner method of playing this animation is necessary.
Video: Good things come in small packages
Digital video has the capability of delivering fast, consistent playback of media in a well-compressed format. Director can export as video. So, why not export this sequence as video and see what happens?
Exporting video from Director is perhaps the easiest task you can perform other than opening or saving a file. You simply go to the file menu and select export. You are then presented with a pop-up menu. In this case, you would specify the frames 100 to 155, select QuickTime as the video format, and click the options button to modify the settings for this format. Keep the default settings for now and return to the first menu. Hit export, enter a filename, and see what happens.
Director created a flawless video of the animation. Now check the file size: 41MB. Not bad; it just cut the file size in half with no loss of quality. Maybe it can do better. Try using Soreson for a compression type. Export a new video and check its file size. What? 1.2MB. You double-click. To your utter astonishment, a formerly 100MB animation is playing smoothly, at the right speed, and it looks great!
At this point, it's pretty obvious what technique to use for the TIFF sequence. It's up to you to import a video in a Director cast and examine its properties. Once you have it in the score, you can use the tempo channel (by double-clicking on it) to wait at that frame until the video is complete.
That worked so well that you're going to export the first animation to video, too. That ought to solve the fluctuating frame rate.
Exporting Lingo-controlled animations
Eager to see the result, you immediately view the video. To your utter astonishment, it's a beautiful still shot of the stage. Nothing is moving in the video because Lingo was used to animate the sprites, and Director doesn't execute Lingo when exporting to video. You're going to have to find a work-around. Before, when selecting the format type Quicktime, you noticed that Director can export AVI and bitmaps as well. However, they don't execute Lingo either. Maybe there's a way of automatically exporting each frame of the animation with Lingo to create a video in the same way as before, using a sequence of pictures.
Indeed, there is a method by Joachim Gola, using Director's own Xtras. But since you're going to use Director to export the animation anyway, why not store the pictures in an external cast that's ready to use, eliminating the need to import the images later?
First, create a new external cast and name it StagePictures. Then, create a movie script that will add pictures of the stage to the cast:
on makeBitmap
NewBitmap = new(#bitmap, castLib "StagePictures")
NewBitmap.picture = the stage.picture
if the keyPressed = RETURN then
castLib( "StagePictures").save()
halt
end if
if the timer > 180 then
castLib( "StagePictures").save()
startTimer
end if
end
The script creates a new empty bitmap member at the next available spot in the cast. Then it fills that member with a picture of the stage. The procedure can be interrupted by hitting the RETURN key, which saves the cast and stops the movie. A timer periodically saves the cast, to avoid running out of memory.
If every Director frame represents a new frame of the animation, use a movie script like this to record each frame:
on exitFrame me
makeBitmap
end
Using Lingo to generate pictures means that any other Lingo commands will also execute. Therefore, when you issue a makeBitmap command, any Lingo-based animation is recorded as well.
Unfortunately, other events -- like sound and transitions -- are lost. These need to be reconstructed in the animation using the still images you just created. It's important to know that using the QuickTime video format records any sounds in channels 1 and 2, and transitions in the score; AVI doesn't.
Download a Director 8 sample movie (Mac or PC format) or a Director 7 cast with the required scripts (Mac or PC) using this technique to record a scrolling text member. In this film, the quad property is used to add perspective to a text member. Changing the scrolltop using Lingo makes it scroll upwards, similar to the text in the Star Wars movie. Converting this animation to video overcomes the jerkiness and speed restraints that occur in the purely Lingo version.
Copyright 1997-2024, Director Online. Article content copyright by respective authors.