1.Papervision3D 관련 class들을 다운받는다. ( http://code.google.com/p/papervision3d/ )
2.Papervision3D는 AS3.0의 기본 계층구조와는 다른 별도의 계층구조를 가지고 있으므로 경우에 따른 상속관계를 잘
따져보아야 한다. (무엇을 상속 받았는가에 따라 가능한 기능이 달라지므로 계층구조를 숙지해야할 필요가 있다.)
3.Papervision3D의 기본 요소(viewPort3D, Sceane3D, Camera3D, BasicRenderEngine )를 익히고 활용해본다.
[SWF (width="640", height="480", frameRate="36", backgroundColor="0xEEEEEE")] //meta tag는 꼭 붙여줍니다.
public class PV3Test1 extends Sprite
{ // 1. ViewPort
private var viewPort:Viewport3D; // 2. Scene3D
private var scene3D:Scene3D; // 3. Camera3D
private var camera3D:Camera3D; // 4. BasicRenderEngine
private var randerEngine:BasicRenderEngine;
//3D Object
private var plan:Plane;
public function PV3Test1()
{
super(); //1.ViewPort 만들고 화면에 붙이기
this.viewPort= new Viewport3D();
this.addChild(this.viewPort); //눈에 보이는 것이므로 addChild //2.Scene3D 만들기
this.scene3D= new Scene3D(); //3.Camera3D 만들기
this.camera3D= new Camera3D();
this.camera3D.zoom=40;
this.camera3D.moveBackward(500); //4.RanderEngine 만들기
this.randerEngine= new BasicRenderEngine();
//3D Object 만들기
this.plan= new Plane();
this.scene3D.addChild(this.plan); //눈에 보이는 것이므로 addChild
위의 코드는 PV3D의 기본 틀이다. 자 이제부터는 위의 기본 요소들을 하나씩 짚어보면서 Papervision3D의 상속관계를 알아본다.
!!!!!상속받은 class로 직접 이동하는 방법.. ctrl
을 누르고 원하는 class 이름 위에 커서를 올리면 이름에 underline이 생깁니다. 그 상태에서 class 이름을
클릭하면 곧바로 해당 class 로 이동하게 됩니다. (mac은 사과를 누르세요~) 이러한 방법으로 잘 모르는 class일지라도
상속관계를 찾아들어가 유추할 수 있는 것입니다.
1. ViewPort3D *상속관계 ViewPort3D -> Sprite
(ViewPort는 Sprite 상속받았으므로 눈에 보이는 것임을 알 수 있다.)
ViewPort는 PV3D에 의해서 만들어지는 화면(이미지/영상)을 플래시에 연결시키는 ... 클래스이다.
PV3D는 flash와는 전혀 다른 독자적인 화면랜더링 방식을 취하기 때문에 PV3D와 flash를 연결해주는 것이 필요하다.
그 역할을 ViewPort가 하는 것이다. { PV3D <--> flash }
2. Scene3D *상속관계 Scene3D -> SceneObject3D -> DisplayObjectContainer3D -> EventDispatcher -> Object (기본 상속관계 뼈대를 벗어나 자기만의 상속관계를 가진다는 것을 알 수 있다.)
Scene3D는 PV3D에서 stage와 같은 역할을 하는 객체이다. 그러므로 container 역할이 필요함( DisplayObjectContainer3D 상속 )
여기서 DisplayObjectContainer3D 는 DisplayObject3D를 담을 수 있는 능력이 있어서
addChild( displayObject3D ) / removeChild / numChildren 와 같은 기능이 가능하다.
( AS3 DisplayObject 기본 계층구조의 DisplayObjectContainer 참조)
3. Camera3D *상속관계 Camera3D -> CameraObject3D -> DisplayObject3D -> DisplayObjectContainer3D -> EventDispatcher -> Object
( DisplayObjectContainer3D을 상속받았다는 것이 매우 중요하다.)
DisplayObject3D ::: 플래시의 Sprite 같은 객체로서
x, y, z, scaleX, scaleY, scaleZ, rotationX, rotationY, rotationZ, alpha, ... addChild/ removeChild 가 가능하다.
기존 flash는 고정 카메라였으나 PV3D에서는 다양한 각도와 움직임이 있기 때문에 상당히 복잡한 메카니즘을 가지게 된다.
4.BasicRenderEngine *상속관계 BasicRenderEngine -> AbstractRenderEngine -> EventDispatcher -> Object
플래쉬는 플래시 플레이어가 알아서 랜더링 해주지만 플래시 플레이어는 DisplayObject를 상속받은 객체만 랜더링 해준다...
PV3D는 DisplayObject를 상속받은게 아니라서.... 별로도 랜더링 해 줄수있는... flashPlayer 같은 객체가 필요하다...!!
그 역할을 RenderEngine이 하는 것이다.
*** Plane (for 3D Object) *상속관계 Plane -> TriangleMesh3D
-> Vertices3D -> DisplayObject3D -> DisplayObjectContainer3D
-> EventDispatcher -> Object
TriangleMesh3D :: 삼각형 면 <--- 안에 내용( material )을 채울 수 있다..
눈에 보이기 위한 최소면 단위는 삼각형이다. (3개 vertexs(점들)이 이루는 최소면 ) 그래서 눈에 보이는 도형들은 모두
TriangleMesh3D 로 만든다. (점 두개가 모이면 선...선은 눈에 보이지 않는다...점 세개가 모이면 면이 된다.
그러므로 최소한의 면은 점 세개가 모여서 만들어진 트라이앵글이다.) 복잡한 도형의 경우 여러개의 triangle을 연결하여
만드는 것이다.
3.Papervision3D 활용 Basic 틀이 되는 코드 만들기 SuperClass: Sprite
[SWF (width="640", height="480", frameRate="36", backgroundColor="0xEEEEEE")] //meta tag는 꼭 붙여줍니다.
public class PV3DTest extends Sprite
{ // 1. ViewPort
private var viewPort:Viewport3D; // 2. Scene3D
private var scene3D:Scene3D; // 3. Camera3D
private var camera3D:Camera3D; // 4. BasicRenderEngine
private var randerEngine:BasicRenderEngine;
//3D Object
private var plan:Plane;
public function PV3DTest()
{
super(); //1.ViewPort 만들고 화면에 붙이기
this.viewPort= new Viewport3D();
this.addChild(this.viewPort); //눈에 보이는 것이므로 addChild //2.Scene3D 만들기
this.scene3D= new Scene3D(); //3.Camera3D 만들기
this.camera3D= new Camera3D();
this.camera3D.zoom=40;
this.camera3D.moveBackward(500); //4.RanderEngine 만들기
this.randerEngine= new BasicRenderEngine();
//3D Object 만들기
this.plan= new Plane();
this.scene3D.addChild(this.plan); //눈에 보이는 것이므로 addChild
내부가 채워지지 않고 뼈대만으로 구성된 사각형 도형이 가운데 축을 중심으로 빙글빙글 돕니다.
참고로 뼈대의 색은 렌덤하게 설정되므로 Test할 때마다 변합니다.
기본이 되는 코드를 별도 class로 만들어 놓으면 기본 사항을 반복하여 코딩하지 않아도 되므로 유용하다.
기본 내용을 포함한 Base3D라는 class를 만들어 저장하고 이것을 Document class로 불러들여 (상속) 활용하도록 해보자.
먼저 flex내에서 Base3D class를 만들기 위한 as 파일을 생성한다.
해당 프로젝트 src폴더에서 오른쪽 마우스 클릭 > new > Actionscript class
팝업이 뜨면 package 이름/ 경로와 as. 파일의 name, 기본적으로 상속받을 Superclass를 지정해준다. (Superclass 시작은 대문자)
package 이름/경로는 본인이 원하는대로 적어주면 자동으로 생성된다.
여기서는 자신이 만든 class를 timo라는 폴더에 넣어두어 관리하고있다.
public class Base3D extends Sprite
{
public var viewPort3D: Viewport3D;
public var scene3D: Scene3D;
public var camera3D: Camera3D;
public var renderEngine: BasicRenderEngine;
public function Base3D( width: Number = 640,
height: Number = 480,
autoScaleToStage: Boolean = false,
interactive: Boolean = false )
{
super(); // 1. viewPort
this.viewPort3D = new Viewport3D( width,height, autoScaleToStage, interactive );
this.addChild( this.viewPort3D ); // 2. stage
this.scene3D = new Scene3D(); // 3. camera
this.camera3D = new Camera3D();
this.camera3D.zoom = 40;
this.camera3D.moveBackward( 500 ); // 4. render
this.renderEngine = new BasicRenderEngine(); // 5. 매 프레임마다 렌더링..
this.addEventListener( Event.ENTER_FRAME, onEnter );
}
private function onEnter( e: Event ): void
{
this.renderEngine.renderScene( this.scene3D, this.camera3D, this.viewPort3D );
}
[SWF (width="640", height="480", frameRate="36", backgroundColor="0xEEEEEE")] //Meta tag는 꼭 써줍니다.
public class PV3Test1 extends Sprite
{ //1. viewPort
private var viewPort:Viewport3D; //2.Sceane3D
private var scene3D:Scene3D; //3.camera
private var camera3D:Camera3D; //4.randerEngine 위 네가지 요소가 기본적으로 필요한 필수사항이므로 머리에 기억하고 있어야 한다.
private var randerEngine:BasicRenderEngine;
private var plan:Plane;
public function PV3Test1()
{
super();
//1. viewPort 만들고 화면에 붙이기::스프라이트를 상속받았으므로 눈에보인다.
this.viewPort= new Viewport3D(640,480,false,false); // autoscale은 화면에 꽉 채울 것인지를 묻는 것임 (false가 기본) //interactive는 인터렉션이 가능하도록 할 것인지를 묻는 것임
this.addChild(this.viewPort);
//this.viewPort.scaleX=2; //기준점을 기준으로 화면 스케일을 쭉~ 늘리는 것임 //화면전환을 하고 싶다면 뷰포트 2개를 만들어서 애드차일드를 번갈아 가면서 한다.
//2.Sceane3D 만들기
this.scene3D= new Scene3D();
//3.camera 만들기
this.camera3D= new Camera3D();
this.camera3D.zoom=40;
this.camera3D.moveBackward(500);
//4.randerEngine 만들기
this.randerEngine= new BasicRenderEngine();
//3D 오브젝트 만들기 // 뼈대 이외의 속성들은 material이라는 것으로 컨트롤 한다.(material은 plane 윗라인에 쓰자)
var material:ColorMaterial= new ColorMaterial(0xFF0000);
material.doubleSided=true;
this.plan= new Plane(material); //뼈대를 만드는 것 !!!!!
this.scene3D.addChild(this.plan);
[ SWF (width="640", height="480", frameRate="36", backgroundColor="0xEEEEEE")]//꼭써주자!!
public class PV3DTest2 extends Base3D
{
private var plane:Plane;
private var plane2:Plane; private var planeContainer:DisplayObject3D;
public function PV3DTest2(width:Number=640, height:Number=480,
autoScaleToStage:Boolean=false, interactive:Boolean=false)
{ //부모클래스의 생성자 호출 base3d의 것 모두 가짐
super(width, height, autoScaleToStage, interactive); //3D 객체 생성하기
this.createObject3D(); //매 프래임마다 할 일 (객체변화주기)
this.addEventListener(Event.ENTER_FRAME, onEnter);
}
private function createObject3D():void
{ //채울물질 만들기 var material:ColorMaterial= new ColorMaterial(0xFF99999); var material2:ColorMaterial= new ColorMaterial(0xFFF078); //material.doubleSided=true;//2개의 plane을 만들 것이므로 더블사이드일 필요가 없으니 지워준다.
//물질이 채워진 면 만들기 this.plane= new Plane(material); //material을 꼭 넣어주어 해당 요소를 적용시킨다. this.plane2= new Plane(material2); //material을 꼭 넣어주어 해당 요소를 적용시킨다. this.plane.rotationY=180;//2개의 plane의 등이 맡닿을 수 있도록 한쪽면을 180도로 회전시킨다.
//this.scene3D.addChild(this.plane);
//this.scene3D.addChild(this.plane2); this.planeContainer= new DisplayObject3D(); this.scene3D.addChild(this.planeContainer); this.planeContainer.addChild(this.plane); this.planeContainer.addChild(this.plane2);
}
private function onEnter(e:Event):void
{
//this.plane.rotationY+=10;
//this.plane2.rotationY+=10; this.planeContainer.rotationY+=10;
}
}//class
}//package
/* 과정
1. case로 활용할 planeContainer라는 변수를 선언한다. 2. plane을 2개 만들어 2개의 material로 각각 다른 색을 입힌다.
3. 두개의 plane을 planeContainer에 담고 planeContainer를 회전시켜준다. 즉 두가지 오브젝트를 한 case에 넣고 case 자체를
회전하는 것이다.
[ SWF( width="640", height="480", frameRate="36", backgroundColor="0xEEEEEE")]
public class PV3DTest3 extends Base3D
{
public function PV3DTest3( width:Number=640, height:Number=480,
autoScaleToStage:Boolean=false, interactive:Boolean=false)
{ // 부모클래스의 생성자 호출..
super(width, height, autoScaleToStage, interactive);
// 3D 객체 생성하기
this.createObject3D();
// 매 프레임마다 할 일... {객체변화주기}
this.addEventListener( Event.ENTER_FRAME, onEnter );
}
private var planeContainer: DisplayObject3D;
private var plane1: Plane;
private var plane2: Plane;
private function createObject3D(): void
{ // 채울 물질 만들기
var material1: ColorMaterial = new ColorMaterial( 0xFF9900 );
var material2: ColorMaterial = new ColorMaterial( 0x0000FF );
// 물질이 채워진 면 만들기
this.plane1 = new Plane( material1, 400, 400 );
this.plane2 = new Plane( material2, 400, 400 );
// this.plane1.x = 200; this.plane2.x = 200;
this.plane2.rotationY = 180;
this.planeContainer = new DisplayObject3D();
this.scene3D.addChild( this.planeContainer );
}
} /* 회전의 중심을 바꾸려면 DisplayObject3D를 Sprite 처럼 활용하자 flash stage와는 다르게 PV3D에서 오브젝트의 중심은 기본적으로 오브젝트의 중심이다. 그러므로 가로 세로길이가 각 400인 오브젝트에서는 그 중심에서 200만큼 증가시키면
한쪽 변을 중심으로 도는 모션을 구현할 수 있다.
노란색 면을 기준으로 하여 왼쪽 모서리를 중심으로 (파란색 면은 오른쪽 모서리) 뱅글뱅글 회전.
[ SWF (width="640", height="480", frameRate="36", backgroundColor="0xEEEEEE")]//꼭써주자!!
public class PV3DTest4 extends Base3D
{
public function PV3DTest4(width:Number=640, height:Number=480,
autoScaleToStage:Boolean=false, interactive:Boolean=false)
{
super(width, height, autoScaleToStage, interactive);
this.createObject3D();
this.addEventListener(Event.ENTER_FRAME, onEnter);
}
private var earth:Sphere;
private function createObject3D(): void
{
var bitmapData:BitmapData= new BitmapData(400,300,false,0); bitmapData.perlinNoise( 128,128,8,12345, true, true);//네번째 트루는 말렸을 때 끝이 매끄럽게 연결하는것 // bitmapData.perlinNoise( 128,128,8,12345, false, true);
var material:BitmapMaterial = new BitmapMaterial(bitmapData);
this.earth= new Sphere(material, 300,20,20) //껍질, 반지름 , 가로세로등분
this.scene3D.addChild(this.earth);
}
private function onEnter(e:Event):void
{
this.earth.rotationX+=2;
this.earth.rotationY+=3;
}
}
}
<변경사항>
Object3D를 만들기 위해 함수 createObject3D를 만든다. perlinNoise를 쓰기위해 bitmapData를 상속받는다.
private var earth: Sphere; private var moon: Sphere; private var moonContainer: DisplayObject3D;
private function createObject3D(): void
{
// 지구 만들기 var material1: BitmapFileMaterial = new BitmapFileMaterial( "./img/world.jpg" );
this.earth = new Sphere( material1, 300, 12, 12 );
this.scene3D.addChild( earth );
this.earth.rotationZ = -20;
// 달 만들기 var material2: BitmapFileMaterial = new BitmapFileMaterial( "./img/img1.jpg" );
this.moon = new Sphere( material2, 50, 8, 8 ); this.moon.x = 450;
// 달을 화면에 붙이기 { moonContainer - moon } this.moonContainer = new DisplayObject3D(); this.moonContainer.rotationZ = -25; this.moonContainer.addChild( moon ); this.scene3D.addChild( this.moonContainer );
}
private function onEnter( e: Event ): void
{ this.earth.rotationY += 1; // 지구 자전 this.moonContainer.rotationY += 2; // 달이 지구를 중심으로 공전 this.moon.rotationY += 1; // 달 자전
// this.earth.rotationX += 3;
}
} // class
} // package
과정 moon의 case역할을 하게 될 moonContainer 변수 만들기 ( DisplayObject3D 임포트) earth와 moon 변수 생성하고 각각 material 처리 오브젝트인 moon의 중심점 x위치를 450 만큼 증가 (earth와의 실질적인 거리차이) moon을 moonContainer 에 넣기 moonContainer를 earth를 중심으로 공전하도록 함 earth를 자전하도록 함
moonContainer에 moon을 넣었기 때문에 earth와 rotationY 를 공유할 수 있는 것임 moonContainer를 쓰지 않았다면 각기 다른 기준점으로 공전/자전을 해야함
그렇게 되면 오브젝트가 많아질 경우 각각 기준점이 다르기 때문에 컨트롤하기가 어려워짐 그러므로 컨테이너를 적극 활용하여 움직임 컨트롤를 쉽게 해야함.
지구와 지구 주위를 도는 달 (달 sphere를 만들고 달의 공전 중심을 지구로 설정합니다. this.moonContainer.rotationY += 2; )
Superclass Base3D (특정 개체의 움직임을 절대 중심에 두고 카메라를 이동 시켜보기 )
private var earth: Sphere;
private var moon: Sphere;
private var moonContainer: DisplayObject3D;
private function createObject3D(): void
{ // 지구 만들기
var material1: BitmapFileMaterial = new BitmapFileMaterial( "./img/world.jpg" );
this.earth = new Sphere( material1, 300, 12, 12 );
this.scene3D.addChild( earth );
this.earth.rotationZ = -20;
// 달 만들기
var material2: BitmapFileMaterial = new BitmapFileMaterial( "./img/img1.jpg" );
this.moon = new Sphere( material2, 50, 8, 8 );
this.moon.x = 450;
// 달을 화면에 붙이기 { moonContainer - moon }
this.moonContainer = new DisplayObject3D();
this.moonContainer.rotationZ = -25;
this.moonContainer.addChild( moon );
this.scene3D.addChild( this.moonContainer );
}
private function onEnter( e: Event ): void
{
this.earth.rotationY += 1; // 지구 자전
this.moonContainer.rotationY += 2; // 달이 지구를 중심으로 공전
this.moon.rotationY += 1; // 달 자전
// this.earth.rotationX += 3;
this.camera3D.x += 0.01 * ( 2000 - this.camera3D.x ); this.camera3D.z += 0.01 * ( 2000 - this.camera3D.z ); this.camera3D.y += 0.01 * ( 2000 - this.camera3D.y ); this.camera3D.lookAt( this.earth ); //이차원에서는 좌우상하로 돌아보기만 하면 되지만 삼차원에서는 좌우상하로 바라보고 / 카메라의 위치도 틀어야 한다. //어려운 프로세스이므로 기본적으로 lookAt(특정개체) 를 제공한다. // lookAt(특정개체)를 쓰면 특정개체의 움직임을 화면 정면으로 바라본 채 카메라가 움직인다. 즉 특정 개체는 항상 화면의 중앙에 놓이게 된다. 특정 개체가 절대기준이 되는 것임. lookAt(특정개체)을 dimmed시키고 실험해보면 차이점을 알수 있다.
}
} // class
} // package
로딩하자마자 달과 지구는 앞으로 zoom in되다가 서서히 zoom out 됩니다. 지구와 달은 중앙에서 벗어나지 않습니다.
다양한 웹사이트와 레퍼런스를 참조한 결과 단순히 다음 코드 한줄로 될 줄 알았습니다만,
보안정책상 마우스나 키보드 이벤트를 받은 후처리로서의 동작으로만 가능하다고 합니다.
즉, 시작부분에 단순히 다음 코드를 삽입해서 자동으로 풀스크린으로 들어가도록 하는것은 동작하지 않는것 같습니다.
stage.displayState = StageDisplayState.FULL_SCREEN;
다음과 같이 메뉴나 버튼등을 활용하여 이벤트 처리시 풀스크린 진입을 가능하게 해주면 됩니다.
아래의 예는 플래시에서 우측클릭시 뜨는 팝업메뉴에 Go Full Screen / Exit full Screen 메뉴를 삽입한 경우입니다.
... 클래스의 constructor 부분에서 다음과 같이 built-in 메뉴를 풀스크린 관련 메뉴 아이템으로 대체, 이벤트 핸들러 선언.
var fullscreenCM:ContextMenu = new ContextMenu();
fullscreenCM.addEventListener(ContextMenuEvent.MENU_SELECT, menuHandler);
fullscreenCM.hideBuiltInItems();
var fs:ContextMenuItem = new ContextMenuItem("Go Full Screen" );
fs.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, goFullScreen);
fullscreenCM.customItems.push( fs );
var xfs:ContextMenuItem = new ContextMenuItem("Exit Full Screen");
xfs.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, exitFullScreen);
fullscreenCM.customItems.push( xfs );
contextMenu = fullscreenCM;
다음과 같이 이벤트 핸들러 구현.
// functions to enter and leave full screen mode
public function goFullScreen(event:ContextMenuEvent):void
{ stage.displayState = StageDisplayState.FULL_SCREEN;
}
public function exitFullScreen(event:ContextMenuEvent):void
{ stage.displayState = StageDisplayState.NORMAL;
}
중요한것은 이걸로 끝이 아니고 publish된 html 파일에서 allowFullScreen 내용들을 true로 수정해 주어야 합니다.
수정하지 않으면 다음과 같이 보안관련 에러가 발생합니다.
기본적으로 Sprite 클래스를 상속받고, Viewport3D, Scene3D, Camera3D, BasicRenderEngine 들을 생성/초기화 한 후,
Event.ENTER_FRAME 의 이벤트헨들러에서 계속적으로 renderScene 을 호출하여 3D 화면을 렌더링 합니다.
아래는 검은 배경에 와이어프레임형태의 구(Sphere)를 하나 그리는 내용입니다.
package { import flash.display.Sprite; import flash.events.Event; import org.papervision3d.cameras.Camera3D; import org.papervision3d.objects.primitives.Sphere; import org.papervision3d.render.BasicRenderEngine; import org.papervision3d.scenes.Scene3D; import org.papervision3d.view.Viewport3D; [SWF(width="640", height="480", backgroundColor="#000000", frameRate="60")] public class HelloPV3D extends Sprite { private var viewport:Viewport3D; private var scene:Scene3D; private var camera:Camera3D; private var renderer:BasicRenderEngine; public function HelloPV3D() { viewport = new Viewport3D(); addChild(viewport); scene = new Scene3D(); camera = new Camera3D(); renderer = new BasicRenderEngine(); var sphere:Sphere = new Sphere(); scene.addChild(sphere); addEventListener(Event.ENTER_FRAME, enterFrameHandler); } private function enterFrameHandler(event:Event):void { renderer.renderScene(scene, camera, viewport); } } }
Viewport3D, Scene3D, Camera3D, BasicRenderEngine 이들이 핵심이라고 할 수 있는데, 이들의 정체를 Reference 에서 살펴보면 다음과 같습니다.
BasicRenderEngine links Viewport3Ds,
Scene3D, and Camera3Ds together
by gathering in all of their data, rendering the data, then calling the
necessary functions to update from the rendered data
한편, 위와 같은 일련의 기본적인 초기화 코드를 구현해 놓은 클래스가 있는데, 바로 BasicView 입니다.
BasicView 를 사용하면 Viewport3D, Scene3D, Camera3D, BasicRenderEngine 초기화 과정을 거치지 않아도 됩니다.
package { import org.papervision3d.objects.primitives.Sphere; import org.papervision3d.view.BasicView; [SWF(width="640", height="480", backgroundColor="#000000", frameRate="60")] public class BasicViewTest extends BasicView { public function BasicViewTest() { var sphere:Sphere = new Sphere(); scene.addChild(sphere); startRendering(); } } }
이때 render.renderScene(scene, camera, viewport) 부분이 startRendering() 으로 바뀐 것을 볼 수 있습니다.
만약 매 프레임 렌더시에 무언가를 하려면 다음과 같이 BasicView 의 render 함수를 오버라이드해서 우리가 구현할 수 있습니다.
package { import flash.events.Event;
import org.papervision3d.objects.primitives.Sphere; import org.papervision3d.view.BasicView; [SWF(width="640", height="480", backgroundColor="#000000", frameRate="60")] public class BasicViewTest extends BasicView { public function BasicViewTest() { var sphere:Sphere = new Sphere(); scene.addChild(sphere); startRendering(); }
override protected function onRenderTick(event:Event=null):void { // 여기서 추가적인 무엇인가를 수행 renderer.renderScene(scene, camera, viewport); }
} }
onRenderTick 은 BasicView 클래스에 구현되어 있습니다만, 우리가 여기서 override 하여 우리만의 추가적인
기능을 부여할 수 있습니다.
import org.papervision3d.materials.ColorMaterial; // 면에 입힐 재질 라이브러리 import org.papervision3d.objects.primitives.Plane; // 면을 위한 라이브러리
[SWF(width="640", height="480", backgroundColor="#ffffff", frameRate="60")]
public class HelloPV3D extends Sprite
{
private var viewport:Viewport3D;
private var scene:Scene3D;
private var camera:Camera3D;
private var renderer:BasicRenderEngine; public var plane:Plane; // Plane(면) 클래스의 인스턴스변수 선언
public function HelloPV3D()
{
viewport = new Viewport3D();
addChild(viewport);
scene = new Scene3D();
camera = new Camera3D();
renderer = new BasicRenderEngine();
var material:ColorMaterial = new ColorMaterial(0x33ddff, 1); // 파란색 재질 생성 material.doubleSided = true;
plane = new Plane(material, 300, 300, 1, 1); // 위에서 만든 재질로 면을 생성
scene.addChild(plane); // 씬에 면을 추가
CS4의 Preferences 의 ActionScript 3.0 Settings 메뉴는 CS3와 달리 위 화면과 같이 세가지로 구분이 되어있습니다. 아래 설명은 Adobe Help 에서 찾은 설명입니다. 참고하세요.
즉 .as 로 존재하는 library 들은 위와같이 첫번째 source path 에 경로를 지정해주면 되고,
.swc 로 존재하는 library 들은 두번째의 library path 에 경로를 지정해주면 됩니다.
이렇게 flash의 Preferences 에서 설정한 라이브러리는 모든 flash파일에 공통적으로 적용이 되고 사용할 수 있으므로, Papervision3D 와 같은 라이브러리는 여기서 설정하여 사용할 수 있게 하면 좋겠죠. (Application level)
각 flash파일에서만 필요한 라이브러리는 해당 파일의 publish setting 화면에서 ActionScript 3.0 Setting 에서 path를 지정해 줄 수 있습니다. (Document level)
Set the location of ActionScript files
To use an ActionScript class that you’ve
defined, Flash must locate the external
ActionScript files that contain the class definition. The list of
folders in which Flash searches for
class definitions is called the classpath for ActionScript
2.0 and the source path for ActionScript 3.0. Classpaths
and source paths exist at the application (global) or document level.
For more information about classpaths, see Classes in Learning ActionScript 2.0 in Adobe Flash or “Packages”
in Programming ActionScript 3.0.
You can set the following
ActionScript locations in Flash:
ActionScript 2.0
Application level (available
to all AS2 FLA files):
Classpath (set in ActionScript
preferences)
Document level (available only to the FLA file that specifies
this path):
Classpath (set in Publish Settings)
ActionScript 3.0
Application level (available
to all AS3 FLA files):
Source path (set in ActionScript
preferences)
Library path (set in ActionScript preferences)
External library path (set in ActionScript preferences)
Document level (available only to the FLA file that specifies
these paths):
Source path (set in Publish Settings)
Library path (set in Publish Settings)
External library path (set in Publish Settings)
Document class (set in Document Property inspector)
In
ActionScript 3.0, there are two additional paths that you can set
to specify the locations of ActionScript resources.
The Library
path specifies the location of pre-compiled ActionScript
code which resides in SWC files you have created. The FLA file that
specifies this path loads every SWC file at the top level of this
path and any other code resources that are specified within the
SWC files themselves. If you use the Library path, be sure none
of the compiled code in the SWC files is duplicated in uncompiled
AS files in the Source path. The redundant code will slow down compilation
of your SWF file.
The External
Library path specifies the location of SWC files that contain
code used for compiler error definitions. This path can be used
to load external code resources in SWC format so that the classes
within them can be used at runtime. When you compile a SWF, the
SWC files in the External Library path are not added to the SWF
file, but the compiler verifies that they are in the locations you specified.
The External Library path is most often used for runtime shared libraries.
For more information about runtime shared libraries, see Working with runtime shared assets. For more information about loading
external code at runtime, see Programming ActionScript 3.0.
For
each type of resource path, you can specify more than one path for Flash to look in. Resources found in
any of the paths specified will be used.
받으신 압축파일은 데스크탑이나 기타 위치에 풀어놓으면 됩니다.
(아래의 경우는 Papervision3D_2.0.869 라는 폴더)
Flash 의 Preference - ActionScript - ActionScript 3.0 Settings 에서 다음과 같이 해당 폴더를 지정해 줍니다.
이렇게 하면 Flash 에서 Papervision3D 에 정의/구현 되어 있는 DisplayObject3D, ViewPort3D 등 3D 관련
Class 들을 사용 할 수 있게 됩니다.
CS3 에서 설정방법
CS4 에서 설정방법
2. 샘플 코드 실행 많은 Papervision3D의 샘플코드들을 받아보면 Document Class 방식으로 되어있어 .as 파일만 존재합니다.
따라서, 이를 실행해보기 위해서는 신규 AS3.0 의 fla 파일을 만들어 해당 class 를 지정해 주어야 합니다.
즉 .as 파일을 실행하기 위한 껍데기(?)가 필요한 것입니다.
새파일을 .as 파일이 있는 폴더에 같이 저장합니다. (fla 로저장되겠죠. 이름은 상관 없습니다)
저장 후, 우측의 Properties 탭에서 Class 라는 부분의 필드에 해당 .as 의 파일명 (=클래스명)을 입력해 줍니다.
이때 .as 는 입력하지 않습니다.
CS3 에서는 화면 아래쪽에 Document Class 라는 필드가 있습니다.
입력후 우측의 연필모양의 버튼을 눌렀을때 .as 파일이 잘 열리면 제대로 연결 지정이 된 겁니다.
즉 새로만든 Test.fla 파일은 지정한 InternalCarousel 이라는 클래스를 사용하여 동작한다고 명시를 해 준 것입니다.
실행을해봅니다. 실행이 되지 않으면 output 창의 로그를 확인하세요. 주로 Papervision3D 라이브러리 패스가
올바르게 설정되지 않은 경우가 많습니다.
Papervision3D 를 보시려면 Document Class 를 알고 시작하면 도움이 많이 됩니다.
아래는 Adobe Help 에 있는 설명입니다. 참고하세요.
Declare an ActionScript 3.0 document class
When you use ActionScript 3.0, a SWF file
may have a top-level class associated with it. This class is called
the document class. When the SWF is loaded by Flash Player, an instance
of this class is created to be the SWF file's top-level object.
This object of a SWF file can be an instance of any custom class
you choose.
For example, a SWF file that implements a calendar
component can associate its top level with a Calendar class, with
methods and properties appropriate to a calendar component. When
the SWF is loaded, Flash Player creates an instance of this Calendar
class.
Deselect all objects on the Stage and in the Timeline
by clicking a blank area of the Stage. This displays the Document
properties in the Property inspector.
Enter the filename of the ActionScript file for the class
in the Document Class text box in the Property inspector. Do not
include the .as filename extension.
Note: You can also enter the Document Class information
in the Publish Settings dialog box.
페이지를 보시면 다음과 같이 레퍼런스와 Programming 가이드 문서가 있습니다.
한글 버전은 주요 Object들의 이름들까지 한글로 번역을 해놓아서 오히려 혼돈의 우려가 있더군요.
(예:Display Object - 표시객체)
따라서, 영문문서를 보는것이 좋습니다. 아래와 같이 문서들이 있습니다.
일단은 Flash 를 기준으로 스터디를 하기 위해 Flash용 문서를 받아 보시면 됩니다.
(ActionScript 에 대한 내용은 기본적으로 같습니다.)
해당 페이지로 들어가셔서 우측 상단을 보시면 PDF 로 다운로드 받을 수 있는 메뉴가 있습니다.
PDF 로 저장해놓고 수시로 볼 수 있는게 좋겠죠.
AS3.0 의 주요 특징 - ActionScript 3.0 goes beyond the scripting capabilities of previous versions of ActionScript. It is designed to facilitate the creation of highly complex applications with large data sets and object-oriented, reusable code bases.
- 새로운 버전의 ActionScript Virtual Machine2 (AVM2) 사용
- ActionScript 3.0 is architecturally and conceptually different from previous versions of ActionScript.
- A single SWF file cannot combine ActionScript 1.0 or 2.0 code with ActionScript 3.0 code.
AS2.0 과의 표면적인 차이점
완전한 프로그래밍 언어의 성격을 갖추면서 변수의 타입을 명확하게 명시를 해주어야 합니다.
기존처럼 타임라인 여기저기서 무비클립등에다가 임의로 이름만 써서 변수를 만들던 방식은 이제 통용불가!
다음과 같이 변수 선언시 var 를 붙이고, 변수이름 뒤에는 : 와 타입명을 명시해주어야 함. var myNumber:Number = 17; var myString:String = "Hello SADI";
class (클래스) 와 object (객체) 그리고 instance(인스턴스) 개념 AS3.0 이 Object Oriented Programming 을 지향하면서 이들의 개념도 알아야 제대로 다룰 수 있게 되었습니다. 이들은 Processing 이나 Java 에 등장하는 class 와 같습니다.
Two words that are often used as synonyms for data type are class and object. A class is simply the definition of a data type—it’s like a template for all objects of the data type, like saying “all variables of the Example data type have these characteristics: A, B, and C.” An object, on the other hand, is just an actual instance of a class; a variable whose data type is MovieClip could be described as a MovieClip object. The following are different ways of saying the same thing:
•The data type of the variable myVariable is Number.
•The variable myVariable is a Number instance.
•The variable myVariable is a Number object.
•The variable myVariable is an instance of the Number class.
즉 class 는 붕어빵 틀과 같은 틀을 말하고 object 나 instance 라는 말은 실제로 찍어낸 붕어빵들을 말합니다.
이벤트 핸들링 AS3.0 에서는 다음과같이 이벤트 리스너 메소드(=함수) 를 만들어놓고, addEventListener 라는 함수로 등록을 해줍니다.