프로그래밍/Flex/AIR2008.09.23 10:13
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.


신고
Posted by 시난
프로그래밍/Flex/AIR2008.09.23 09:47
source:
http://www.barbarayersin.com/2008/04/how-to-display-text-in-papervision.html


I've been looking for a tutorial to display a simple text field within papervision without much success. I finally tumbled on this blog post where it was quite well explained. The example however might be a little long to demonstrate my sole purpose: how to display text in papervision.

So I've decided to put here an even simpler example to make things crystal clear:


// create your text field and set its content.
var t:TextField = new TextField();
t.text = "Hello world!";
// create a BitmapData of your wished width and height
var bitmap:BitmapData = new BitmapData(100,100);
// Fill bmp with the content of your TextField.
//It's as if you took a picture of t.

bitmap.draw(t);
// Create a material with the resulting BitmapData and you can use it on any DisplayObject3D!
var material:BitmapMaterial = new BitmapMaterial(bitmap);
material.smooth = true;
material.doubleSided = true;
var p:Plane = new Plane(material,100,100);
scene.addChild(p);


First observation is that it seems impossible to directly embed a UIComponent within papervision *sigh*. Whatever the UIComponent (Button, TextField, etc), it has to be put somehow in a texture and applied on a DisplayObject3D such as a Plane.

Or at least, I have no knowledge of another way to do it. Does anybody know better? My worry is that it may slow down the frame rate to display text in a texture rather than directly as what it really is: good old plain text.
신고
Posted by 시난
프로그래밍/Flex/AIR2008.09.23 09:41
source:
http://joshua.almirun.com/tech/ria/flash/getting-2d-coords-from-displayobject3d

I have been banging my head against a wall with a simple Papervision3D problem: making a normal Flash 2D object (a DisplayObject, or Sprite) to appear at the same coordinates as a 3D object (a DisplayObject3D, or Plane, or whatever).

After spending the best part of a day scouring mailing lists, I found this method that solved the problem:

public function convertTo2DCoords(o:DisplayObject3D, camera:CameraObject3D, offsetX:Number = 0, offsetY:Number = 0):Point {
var view:Matrix3D = o.view;
var persp:Number = (camera.focus * camera.zoom) / (camera.focus + view.n34);
return new Point((view.n14 * persp) + offsetX, (view.n24 * persp) + offsetY);
}

You just need to add half the Stage.width to point.x, and half the Stage.height to point.y, and Bob’s your uncle …

(I was working with a 3D scene that filled the whole stage … might need some tweaking if this is not the case …)

I am posting this because, although it’s apparently a quite basic Papervision problem, it took ages to find it. We need better PV3D documentation!





신고
Posted by 시난
프로그래밍/Flex/AIR2008.09.23 00:37
PicLens처럼 꾸며보기..
조금 다르지만 ^^;


데모:
http://lostsin.cafe24.com/flex/book_search/

300k 정도네..
모듈화 해야겠지...



신고
Posted by 시난
프로그래밍/Flex/AIR2008.09.02 01:34
http://joshua.almirun.com/tech/3d/papervision3d-airs-htmlloader-vanity-cube

AIR를 다운 받고 소스를 보면 알 수 있습니다.

<textarea name="code" class="as3">public function BrowserCubeContainer() { scene = new MovieScene3D(this); camera = new Camera3D(); camera.z = -900; camera.zoom = 5; materials = []; var size:int = 800; cube = new Cube(new MaterialsList({ bottom : createBrowserFace("http://micapam.innariddim.com/"), back : createBrowserFace("http://joshua.almirun.com/"), right : createBrowserFace("http://linkedin.com/in/joshuamostafa"), top : createBrowserFace("http://cfour.com.au/"), front : createBrowserFace("http://media.almirun.com/photos/"), left : createBrowserFace("http://www.vtc.com/modules/products/authorInfo.php?author=107") }), size, size, size, 10, 10, 10); scene.addChild(cube); cube.x = 500; cube.y = 200; addEventListener(Event.ENTER_FRAME, handleEnterFrameEvent); } public function render():void { for (var i:Number = 0; i < materials.length; i++) { (materials[i] as MovieMaterial).updateBitmap(); } cube.rotationX += 1.35; cube.rotationY += 2.55; cube.rotationZ += 0.55; scene.renderCamera(camera); } public function handleEnterFrameEvent(event:Event):void { render(); } private function createBrowserFace(url:String):MovieMaterial { var html:HTMLLoader = new HTMLLoader(); var urlReq:URLRequest = new URLRequest(url); html.width = 800; html.height = 800; html.load(urlReq); var movie:MovieMaterial = new MovieMaterial(html); materials.push(movie); return movie; } </textarea>
눈여겨 볼 부분은 MaterialsList를 생성하는 도중
createBrowserFace() 호출 부분과
var movie:MovieMaterial = new MovieMaterial(html);

 render()가 일어나는 도중
 (materials[i] as MovieMaterial).updateBitmap(); 부분입니다.

정확히 flex 구조를 아는 것은 아니지만 짐작컨데
 addChild() 하지 않는 이상 bitmap이 생성되지 않을 겁니다.

 이렇게 되면 MovieMaterial의 생성자로 DisplayObject가 들어간다고 해도
 bitmapData가 초기화되지 않았기 때문에
 MovieMaterial 이 검게 나올 겁니다.

제대로 동작하기 위해 updateBitmap() 처리를 한 것입니다. (불확실)
신고
Posted by 시난
프로그래밍/Flex/AIR2008.08.11 17:48
리뷰/웹사이트2008.08.10 12:25
http://papercritters.com/


Papervision3D 를 이용한 종이 인형 제작 사이트입니다.

사용자 삽입 이미지
사용자 삽입 이미지
사용자 삽입 이미지

자신이 직접 3D 인형을 제작할 수 있으며 (눈코입 등의 스티커 같은 개념만 가능합니다. 현재는)
제작한 것은 등록되고
타인과 공유가 가능합니다. 따라서 인기도 개념도 존재하고.
웹 상에서 배포도 가능합니다.

이런 예술적인(?) 분야의 Web2.0 서비스들이 차근차근 많아지고 있네요.
모래 그림 그리기(Sant Art)를 이것처럼 만들어도 괜찮을 듯 싶습니다.


신고
Posted by 시난
프로그래밍/Flex/AIR2008.08.09 22:18
http://blog.zupko.info/
Andy Zupko - Flash Experimentation, tutorials, and portfolio.


Andy Zupko 님의 블로그입니다.
주로 BitmapData, Papervision3D, Pixel
실험적인 것들을 만나보실 수 있습니다.

모래 효과가 젤 멋지네요 ^^;
신고
Posted by 시난
프로그래밍/Flex/AIR2008.08.09 22:01
조금 지난 일이지만..
Papervision3D를 사용한 특수효과들이
GreateWhite 버전으로 업데이트 되었다.
이로써 PV3D 2.0버전에서도  이 효과를 쓸 수 있게 되었다.

새로운 버전:
Papervision3d Effect Classes for Great White

예전 데모보기:
http://www.tink.ws/blog/papervision3d-effects-for-flex-source/

신고
Posted by 시난
프로그래밍/Flex/AIR2008.06.27 00:16

Papervision3D 연습:
FreeCamera3D, Sphere, BitmapFileMeterial, Tweener




데모:

http://lostsin.hosting.paran.com/flex/solarsystem/


으흐- 지돌스타님 글에 힘입어 자기 전에 살짜기 포스팅..

-.-; 카메라 이상해요....


첫화면 나오면.. 무조건 클릭~

행성/항성들을 클릭하세욤.. -.-;;


참고자료..

1. flex GeoGlobe: http://www.adobe.com/newsletters/edge/june2008/articles/article2/index.html

2. Papervision3D: Click then Camera Move using Tweener

신고
Posted by 시난