January 10th, 2009
Cache Me If You Can
At Infrared5, one thing we do to give us a good boost of speed in Flash is using a technique called (at least by me) Bitmap Injection. The idea behind bitmap injection is to swap out pre-rendered frames of an animated clip into a bitmap object. This removes the extra draw call of a MovieClip, thus speeding things up. Since you can simply change the bitmapData property of a Bitmap, it simply reassigns what it is drawing, rather than having to copyPixels or do any of those performance killers. Since we do it at work, and since Papervision is driven by bitmapData objects - I decided to whip up a quick material which could save your life.
A normal MovieMaterial, when set to animated, redraws the bitmap it is using for every frame of your rendering. As you can imagine, this costs serious CPU, and if you have too many animated materials, your application will slow to a crawl.
So, I wrote up MovieCacheMaterial. The name says it all really. The material draws every frame of the movie into a global array for that particular asset. Then, if the movie is ever on that same frame again, instead of redrawing the movie, it simply draws the 3D content using the already cached bitmap. Then, any other DisplayObject3Ds using that same MovieClip will use the same cache as well. So, your performance on the first loop will be the same as a normal MovieMaterial, but after that, the performance is equivalent to a normal BitmapMaterial - even though there is animation on it!
I wrote a hack work-around for the first loop issue, which might be of use to you. You can call material.ripMovie(stage, frameRate, completeHandler). You pass in the stage, how fast you want the movie to be ripped into the cache, and what function to call when it is complete. The material will set your stage FPS to your desired number, then when it has ripped every frame of the MovieClip that was assigned to it, it will call the function you pass in as completeHandler. This will make it so when you start your application you can have the best performance right off the bat. Obviously it will take it longer to start up, however, since it has to rip your animation before beginning.
You are amazing Andy - What’s the catch?
Unfortunately, there are some limitations to using this material. The first limitation is that it is a memory hog. Since you draw every frame of your Movie into memory, that much more memory is going to be used. To give you an idea of how much that equals: the animation in the demo above is ~150 frames, and is 512×512. When it is fully parsed it uses about 140 megs of memory. Smaller movies will obviously use less. It is definitely something you need to be aware of however.
Second limitation: it doesn’t work with real time dynamic movies or interactions. Remember, it simply draws every frame of a movieclip. That content can be dynamic the first loop, but after that, you are going to see exactly what happened the first time over and over again. This obviously rules out any Virtual Mouse behaviors on a movie as well. But, if you have a simple animation you want to loop - go for it!
And In the End
One other final thing to point out is that you can control your animation by changing your currentFrame on the MovieClip just like normal. It won’t mess up the caching, so you can pause, play, skip, etc. just like normal. In the demo, you can press “F” to jump to the middle of the animation - using a gotoAndPlay.
Anyways - thats about all there is to say about it. You can see the performance difference on the demo. For me, on 49 planes, i get about 25 FPS with MovieCacheMaterial, and about 5 FPS with regular animated MovieMaterial.
and
Feel free to report any bugs. I probably won’t fix any, but it might help others :) Also, you might have noticed I bolded certain words throughout the post. If you can guess why I will give you a free copy of my upcoming top secret application (still a little ways off).
Enjoy!





