November 10, 2008

Misconceptions about how Flash CS4 implements 3D

Emanuele commented on Keith Peter's blog:
"The reality is that there very little 3D code inside the player, at least native code. Whenever you export a movie that uses the new “3D” features, you’ll notice that about 13KB of AS3 code is attached to it. This code is responsible for the pseudo 3D rendering using same old tricks used by earlier 3D renderers. You see degradation in rendering because those vector objects are transformed into cached bitmaps and handled as texture over triangles. Bitmap resampling algorithms inside the player are pretty good, but not good enough in several situations like this one. The Flash IDE, however, does a good job by making completely transparent to the user that this 3D manipulation is not native to the player itself but rather to silently attached code."

(here comes the snark)
How then am I able to paste one line of code into FlashDevelop and get a perspective-correct 3D rotation?

myMovieClip['rotationX'] = 60;

And my SWF isn't 13 KB, it's 1 KB. So apparently Flash Player 10 doesn't need any "pseudo 3D tricks". Sorry to be Mr. Snarky McSnarksalot, but saying "3D manipulation is not native to the player itself" is just asking for it.

So what is that extra code injected by Flash CS4 actually doing? If you have ASV, you don't have to guess; you can just decompile the SWF and take a look. You won't find any secret calls to drawTriangles(), or even the word "triangle" anywhere (sorry Keith).

What you will find are fl.motion classes. Remember those from Flash CS3? I wrote those to implement the Copy Motion as AS3 feature. For CS4, Rebecca Sun updated them to support 3D properties like rotationX, etc. What happens is that when a CS4 motion tween uses 3D, all of the tween properties are controlled with the Animator3D class. This includes the simple ones like x and y. However, if you don't use 3D, the tween is implemented with SWF tags as it has been for a decade.

Why the dramatic change in tween implementation when you use 3D? It boils down to Adobe deciding not to define new SWF tags for 3D features. I'm not going to comment here on the pros and cons of that decision. The practical result, though, is that 3D motion must be scripted, whether by you or by IDE-generated code. And apparently it's still the case that a movie clip is controlled either by the timeline (i.e. with SWF tags) or by ActionScript. I remember being surprised by this in Flash 4, when one tellTarget to _xscale would break a timeline tween permanently.

The Animator3D class may look complex, but it's not doing any rendering per se; it's doing motion. The rendering code is merely a few assignments to:

this._target.transform.matrix3D

There are a lot of Matrix3D manipulations going on. But they are mainly to convert friendly properties like rotationX to coefficients, and to interpolate between matrices. The Animator and Animator3D classes also have to make all scaling and rotation relative to the transformation point, not the origin. This is trickier than you might think.

I hope this helps explain what's going on with that extra 3D code. The moral of this story could also be a nice tagline for ActionScript Viewer:

ASV: Don't guess what's in your SWF. Know it.