http://blog.computerelibol.com/?p=3

Recently, I used papervision for a project. I needed to create a carousel like 3D system. Even though I think it would be helpful and interesting to some to write about the carousel, I’m going to focus on the equations this task led me to instead. I think they’ll prove to be very useful to anyone that needs to match design compositions with pixel perfect precision. To really get the most out of this article, you’ll need some papervision experience. Having made a carousel will help too At the moment, I’m unable to share any working example of the carousel, but at some point I should be able to post an example.

[**Update 08/22/2008:** The equations in this article and in the
source will only work for builds prior to 639. I am in the process of writing an
article about a set of functions that should achieve these effects for versions
of papervision after 639. I am leaving this article intact for educational
purposes.]

[**Update 08/15/2008:** sample
source - it is not the carousel, but it demonstrates the use of the
equations pretty well.]

**Carousel Explained**

Think of a carousel as having the
interactive properties of an ordinary list component. The way this (and probably
all) carousels work is by displaying a collection of selectable items on the
screen. Only one item is selectable at a time. The selected item is visually
distinguishable in some way (highlighted, repositioned, etc.) In our carousel,
the selected item is distinguished by repositioning it to the center of the
collection of items. The items to the left and to the right of the selected item
are rotated slightly, and moved down the z axis to create the contrast needed
between selected and deselected items. With papervision, the display object for
each item is typically a Plane, but anything can be used.

**Scaling: Problem**

The problem started out with having the
selected plane object to display at the scale of the design composition I was
given. Usually, the projects we do don’t have any 3D UI. Consequently, we have
no process for exporting Collada, since the medium the composition is designed
in cannot actually produce such a format (Please let me know if there is a way
to export Collada from After Effects.) Consequently, I was left to replicate the
composition by measuring 3D data on a 2D plane.

**Scaling: Solution**

I soon came to realize that I
essentially needed to be able to negate perspective (later this becomes even
more critical since I need to apply perspective to 2D measurements, and negate
perspective from 3D measurements), but I wasn’t exactly sure about how to do
this. I started by trying different constants on the cameras zoom and focus
properties, I kept the object Z at 100, and camera focus at default (100)
because this obviously had a lot to do with whether the object was at the
intended scale. I did find some constants that gave me the results I was looking
for, but at a Z position of 100, I was getting hardcore perspective
distortion.

After some revisions, I checked out the papervision source and came across the equation for computing perspective. It looks like this:

perspective = focus*zoom/(focus+screenZ)

screenZ is the distance between said DisplayObject3D from the camera on the z axis, focus and zoom are properties of the camera, or in other words, our perspective of the object. Given that the object and camera both have zero rotation, or, possibly a right angle or 180 depending on the object type, modifying any one of focus, zoom, or screenZ(which can be computed, -cam.z + targetZ or just object.screen.z if the object is already in position) to a certain value always produced a pixel perfect match to the composition. After spacing out into a series of day dreams, and some trial and error, I came up with equations that will solve for any of the variables, which when set, will produce the correct distance between the camera and an object to display it at a scale that matches a regular DisplayObject as it would be if you were to simply add it to the stage, that is, as opposed to making it the material of a Plane, and possibly other display types.

**Scaling: Equations**

//Solve for cam.zoom

cam.zoom = (cam.focus + item.screen.z) / cam.focus;

//Solve for cam.focus

cam.focus = item.screen.z / (cam.zoom * (1-1/cam.zoom));

//Solve for screenZ

screenZ = cam.focus*cam.zoom-cam.focus;

//Or

screenZ = -cam.z + targetZ;

//This is obviously pointless when you have a reference to item.screen.z, but useful if you're

//precomputing before a transition. negate perspective from screenX/screenY

var negatePersp:Number = 1/(cam.focus*cam.zoom/(cam.focus + item.screen.z));

**Positioning: Problem**

Being able to get the position that
a 2D coordinate should have on the x/z plane or the y/z plane was also
necessary. I needed to evenly distribute unselected objects over the left and
the right areas of the selected object.

**Positioning: Solution**

We need a way to compute the x
position that a plane should have based on a limited amount of screen real
estate on the x axis at some variable z position. We will need some predefined
variables. *item* is the Plane we’re computing the x position for,
*cam* is our Camera3D, and *xArea* is the area we have to display
objects on the left or right side of the selected object. Note that in the
actual carousel, I only compute these values once, and use them as needed during
transitions. The main difference is that a predefined z position is used to
compute screenZ, which would take the place of item.screen.z.

**Positioning: Equations**

//Compute the perspective

var persp:Number = cam.focus*cam.zoom/(cam.focus + item.screen.z);

//Compute half of the width of the item at item.screen.z,

//we need this value because the registration point of 3D display objects are at their center,

//and we don't want objects falling outside of xArea

var perspItemWidth:Number = item.width/2*persp;

//The following operation gives us a value which will produce the inverse ratio of persp

var negatePersp:Number = 1/persp;

//First subtract item.width,

//which we've computed perspective for at item.screen.z from xArea,

//then apply the inverse operation of perspective on xArea,

//we should think of xArea as if it were the screen.x of an object at item.sceen.z

var negatedXArea:Number = (xArea-perspItemWidth)*negatedPersp;

**Inverse Ratio of Perspective Explained**

Let’s say xArea is
a 2D object at 0,0 with a width of 100. It’s taking up 100 pixels on the screen
on the x axis. If we want to evenly distribute objects across this area at a z
position of 1300, we can’t just use the width of xArea to compute the
distribution. Let’s say we magically add a z property to xArea, and we send it
to z position 1300. Now that it’s further away, it doesn’t take up as much space
as it did when it was right in our face, so it doesn’t take up the 100 pixels of
screen space that we need it to. What we do is compute the perspective to apply
to an object at such a distance, and then we divide 1 by the perspective to get
the inverse ratio of the perspective. We then multiply our new ratio by the
width of xArea (100.) This gives us the distribution scale we need (127) in
order to use a screen pixel width of 100 (as opposed to 78) at z position 1300.
We can say that we need to distribute objects across 127 “papervision 3D units”
in order to distribute them evenly across 100 screen pixels at a z position of
1300.

#### '프로그래밍 > Flex/AIR' 카테고리의 다른 글

[Flex] Tip 모음 (0) | 2008.10.29 |
---|---|

[Flash] 플래시 보안 정책 관련 링크 (0) | 2008.10.22 |

[펌] Plane Scaling and Positioning with Papervision (0) | 2008.09.23 |

[펌] how-to-display-text-in-papervision (0) | 2008.09.23 |

[펌] getting-2d-coords-from-displayobject3d (0) | 2008.09.23 |

네이버 책 검색 (6) | 2008.09.23 |