Source:
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.
댓글을 달아 주세요
비밀댓글입니다
2009.11.10 19:41 [ ADDR : EDIT/ DEL : REPLY ]
그럼 좋은 하루 되세요!
2009.11.11 12:07 신고 [ ADDR : EDIT/ DEL ]요즘 Flex 하긴 하나?
2009.11.12 08:32 [ ADDR : EDIT/ DEL : REPLY ]할일이 없네! 요즘은 자바스크립트 파고 있지^^;;
2009.11.12 14:00 신고 [ ADDR : EDIT/ DEL ]좋은 위젯 잘 쓰고 있습니다.
2010.03.19 21:08 신고 [ ADDR : EDIT/ DEL : REPLY ]tistory에서 사이즈가 안 맞아 수정하러 찾아왔는데, 저는 위와 같이 위젯 편집 버튼이 보이지 않는데, 어떻게 된걸까요?
Coach Outlet Store Online
2011.08.28 10:30 [ ADDR : EDIT/ DEL : REPLY ]