Through many experiments, we made some observations about the perspectiveProjection property of display objects which might be helpful to developers. We list them below and illustrate by the examples on the following pages. Let's begin by recalling the basic features of the PerspectiveProjection class.
Basic facts about PerspectiveProjection
Instances of the PerpectiveProjection class are created the usual way. For example:
var pp:PerspectiveProjection=new PerspectiveProjection();
Each instance, say pp, of PerspectiveProjection has three properties:
fieldOfView is a number sharply between 0 and 180 which represents the viewing angle and is responsible for the amout of perspective distortion (the higher value the more distortion). projectionCenter is a Point, e.g.:
projectionCenter, also known as the 'vanishing point', is the point to which points farther from the observer are getting closer to.
focalLength and fieldOfView are interdependent: setting one of them sets the other automatically. It is more intuitive to manipulate the view angle, fieldOfView. Regardless to what object pp is assigned, focalLength is calculated according to the formula: focalLength=stageWidth/2*(cos(fieldOfView/2)/sin(fieldOfView/2)).
The only display object which has a deafult non-null perspective projection is the root object, that is; in our case the MainTimeline. The default fieldOfView is 55 degrees, the default projectionCenter is (stageWidth/2,stageHeight/2); that is, the center of the stage. You can access and manipulate the root's perspectiveProjection property (which is an instance of the PerspectiveProjection class) via:
In a timeline script, you can use: this.transform.perspectiveProjection instead (as in our examples).
Manipulating the root's perspectiveProjection is easy and often sufficient for your purposes. For example, if you have only one 3D object in your movie, you set root.transform.perspectiveProjection.projectionCenter to the center of your 3D object, set the fieldOfView any way you want, and all is fine. If you have several 3D objects, however, that may not work well. The default projectionCenter of the root (or its projectionCenter moved in order to make one of the objects appear better) may create unpleasant effects for other 3D objects. You could see in the example on the previous page how awful the three tiles looked with the default perspectiveProjection, in particular, with the default projectionCenter. Thus, very often, we need to assign separate PerspectiveProjection instances to individual display objects. We showed one way of doing the on the first page. Through experimentation, we also discovered that individual PerspectiveProjection assignments are quirky and one has to be mindful of those quirks.
Assigning PerspectiveProjection to individual display objects - observed behavior
Let's look at the upper tile in the example on the first page. A Bitmap, img1, is placed in a Sprite, holder1, in such a way that the registration points falls in the middle. holder1 is, in turn, a child of a Sprite, container1, whose registation point, (0,0), is also in the middle. A custom PerpectiveProjection object pp1 is assigned to container1:
var pp1:PerspectiveProjection=new PerspectiveProjection();
Once a PerspectiveProjection object is assigned to container1, it will apply to its 3D children. In particular, to holder1 which, on ENTER_FRAME rotates about the y-axis:
We expect to see rotation about the vertical axis passing through the center (0,0) of the tile, with the vanishing point in the middle of the tile. This is, indeed, what we see. However, this behavior will hold only provided container1 is a 2D display object. (Every display object is a 2D object until any of the 3D methods, such as the z-coordinate or rotationX or rotationY are used on it. When they are used, the object's matrix3D becomes non-null and the object is considered a 3D object.) The moment container1 becomes a 3D object, things change dramatically. In particular, the coordinates, (0,0), of the projectionCenter are now considered relative to the stage. To see that effect, take a look at the Experiment 2 on the next page where you can change container1 from a 2D to a 3D object and back.
Here is, then, the first observation:
- If a PerpectiveProjection instance is assigned to a 2D display object, the coordinates of the projectionCenter of the instance are interpreted as coordinates relative to that object. If a PerpectiveProjection instance is assigned to a 3D display object, the coordinates of its projectionCenter are interpreted as coordinates relative to the stage, or, more generally, to the object's first 2D parent. fieldOfView is unaffected regardless if the object is 2D or 3D.
What will happen if we leave container1 as is but assign pp1 as the perspectiveProjection property of its child holder1? This is what we did in Experiment 3 on page 3 of this tutorial. In that case, container1 is the first 2D parent of holder1, and since (0,0) in holder1 and (0,0) in container1 coincide, nothing changes in the way the upper tile rotates. (Excpet for the fieldOfView of pp1 which we changed to 130 for other purposes.) However, if container1 is made into a 3D object the assignment of pp1 to holder1 is ignored completely and holder1 inherits perspective projection settings from the stage. To summarize:
- If a PerpectiveProjection instance is assigned to a display object (2D or 3D alike), say holder, which has a 3D parent without a PerspectiveProjection assignment, the assignment to holder is completely ignored in both fieldOfView and projectionCenter aspects, and all projection settings of holder are inherited from the root perspective projection. (Or from the first 2D or 3D parent with a PerspectiveProjection assignment.)
Our final experiment on page 4 of this tutorial, shows the simplest way to assign an individual PerspectiveProjection and at the same time tests our previous rules. In the applet on page 4, there is no container1 or container2. holder1 and holder2 are children of the MainTimline - 3D objects as they rotate. The MainTimeline is the first 2D parent. Since holders are 3D objects, the projectionCenter for each of them has to be set in terms of coordinates of the centers of holder1 and holder2 relative to the stage. The way of assigning PerspectiveProjection in the applet on page 4 is simple, but it is not very elegant or convenient.
- Download all the source files corresponding to this tutorial: pp.zip
The next three pages contain applets that illustrate the observations above.