I. 3D in Flash
Adobe 가 Flash 를 인수하면서 새롭게 바뀐 것 중에 하나가 바로 ActionScript(AS) 이다. 이전 AS가 단순히 모션에 도움을 주는 Script 였다면 최근 AS3는 Language 에 더 가까워 지고 있는 것 같다. 이는 FLEX나 AIR를 통해 더욱 확실히 알 수 있다. 이런 변화를 통해 AS를 이전까지는 힘들게 여겨지던 기술들도 속속 AS3를 통해서 등장하고 있다. 그 중 하나가 플래쉬를 이용한 3D이다. 예전부터 이러한 시도는 꾸준히 있어왔는데 사실 AS2 의 한계로 실제 필드에서 사용하기에는 무리가 많았다. 하지만 최근 여러 3D라이브러리가 나오면서 불가능하게만 여겨지던 3D영역이 손쉽게 개발되고 있다.
현재 널리 알려져 있는 라이브러리로는 Sandy3D, Papervision3D, Away3D 등이 있는데 각각 장단점이 있는 것 같으나 전부 속속들이 들여다 보지는 못해서 아직 정확한 성능의 차이나 사용상의 용이성등의 평가는 어렵다. 이번 글에서는 셋중 실제 홈페이지에 가장 많이 적용되고 있는 Papervision3D (PV3D)를 기준으로 작성하였다. PV3D는 실무에서도 많이 쓰이고 있을 뿐 아니라 개발 또 한 활발히 이뤄지고 있어 앞으로 더욱 기대되는 라이브러리 이다. 참고로 사용된 PV3D의 버전은 2.0a GreatWhite 이다.
II. Object Build Solution
이번에 테스트 해본 오브젝트 생성 방법은 총 4가지 이다. 첫번째는 PV3D에 기본으로 있는 Object Class를 이용한 방법이고, 두번째는 AS3 Geom Class Exporter를 이용한 방법, 세번째는 DAE 파일을 PV3D의 기본 collada 클래스로 생성한 방법이고 마지막은 같은 DAE 파일을 ASCollada의 DAE 클래스로 생성한 방법이다.
1. 기본 내장 클래스
PV3D는 기본적으로 org.papervision3d.objects 패키지에서 오브젝트를 선언하고 있다. 하위로 종류별로 parsers, primitives, spceial로 구분되며 이 구문에서는 primitives 안의 기본 오브젝트들로 생성하였다.
var cube:Cube = new Cube(materialList, 100, 100, 100); var cone:Cone = new Cone(new WireframeMaterial(0xFF0000)); var sphere:Sphere = new Sphere(new WireframeMaterial(0xFF0000));
가장 빠른 성능을 보이지만 기본으로 제공하는 이외의 형태를 만들지 못하기 때문에 UI 나 Navigation 이 외에는 활용성 면에서는 조금 부족하지 않나 싶다. 결국 사용자화된 오브젝트를 쓰기 위해서는 외부파일을 로드 해야만 한다.
2. AS3 Geom Class Exporter
이는 3D MAX 에서 AS3 Geom Exporter라는 Max Script를 설치하여서 각 라이브러리 별 .as파일로 바로 export하는 방법이다. 이 방법 또한 각 라이브러리에 맞게 .as파일을 만들어 주기 때문에 성능면에서는 좋지만 이름에서 처럼 Geom 에 대한 데이터만 만들어 주기 때문에 위치나 맵핑에 관한 정보없이 단순한 오브젝트만 만들어 주는 것같다. 결국 애니메이션과 맵핑을 위해서 손이 한번 더 가야 한다.
test = new Test(new WireframeMaterial(0xFF0000));
3. Collada
collada 는 뒤에 좀 더 자세히 설명하겠지만 간단히 말해서 3D데이터를 표준 XML 로 만들어주는 프로젝트이다. 확장자는 .dae 를 사용한다. 이 방법은 PV3D에서 기본으로 지원하던 collada 클래스를 이용하는 방법이다.
collada = new Collada("test.DAE" , materialList);
4. DAE
이 방법은 위의 방법과 .dae 파일을 사용한다는 점에서 동일하나 .dae 파일을 파싱하는 클래스가 Collada 가 아닌 DAE 이다. 두 파일의 차이는 DAE는 ASCollada 프로젝트의 파일을 PV3D에 합친것으로 이는 PV3D 2.0a 이후 버전에 적용되었다. 또한 위의 방법과 결정적 차이는 .dae파일의 Animation 을 컨트롤 할 수 있다는 점이다.
dae = new DAE(); dae.animate = true; dae.load("test.DAE", materialList);
III. Collada
collada의 정의를 홈페이지에서 보면 다음과 같이 규정하고 있다. ‘COLLADA is an open digital-asset exchange schema for the interactive 3D industry’ collada 에는 대부분의 3D 데이터가 저장되는데 특히 맵핑과 애니메이션이 매우 유용하다. 3D MAX 와 같은 프로그램에서 모델링과 맵핑을 하고 이를 collada로 export 한 후 PV3D 를 통해 Flash 에 바로 적용 할 수 있기 때문이다. 참고로 3D MAX 에서 collada 파일을 export 하기 위해서는 ColladaMax 같은 플러그인을 별도로 설치 해야한다.
IV. Example
위에서 말한 4가지 방법으로 예제를 만들어 보았다. 아래 소스를 보면 알 수 있겠지만 똑같은 조건하에 오브젝트만 생성하고 있는데 생성되어지는 기본값이 조금씩 상이한 것을 알 수 있다. 특히 같은 .dae 파일을 사용하는 Collada 와 DAE 클래스의 다른 점을 눈여겨 볼 필요가 있을 것 같다.
package { import fl.events.ScrollEvent; import fl.events.SliderEvent; import flash.display.*; import flash.filters.*; import flash.display.Stage; import flash.events.*; import flash.ui.Mouse; import org.papervision3d.core.proto.DisplayObjectContainer3D; import org.papervision3d.objects.parsers.Collada; import org.papervision3d.objects.parsers.DAE; // Import Papervision3D import org.papervision3d.cameras.*; import org.papervision3d.scenes.*; import org.papervision3d.objects.*; import org.papervision3d.objects.special.*; import org.papervision3d.objects.primitives.*; import org.papervision3d.materials.*; import org.papervision3d.materials.special.*; import org.papervision3d.materials.shaders.*; import org.papervision3d.materials.utils.*; import org.papervision3d.materials.utils.MaterialsList; import org.papervision3d.lights.*; import org.papervision3d.render.*; import org.papervision3d.view.*; import org.papervision3d.events.*; import org.papervision3d.core.utils.*; import org.papervision3d.core.utils.virtualmouse.VirtualMouse; import Test; public class TestObject extends MovieClip { public var viewport :Viewport3D; public var scene :Scene3D; public var camera :Camera3D; public var renderer :BasicRenderEngine; private var materialList : MaterialsList; private var cont:DisplayObject3D; private var test:Test; private var collada:Collada; private var dae:DAE; public function TestObject() { init(); } public function init():void { stage.scaleMode = "noScale" stage.showDefaultContextMenu = false; init3D(); addEventListener( Event.ENTER_FRAME, loop ); for (var i:int = 1; i < 5; i++) { this.getChildByName("btn"+i).addEventListener( MouseEvent.CLICK, clickHandler ); } function clickHandler( e:MouseEvent ):void { changeObject( e.currentTarget.name ); } this.getChildByName("carZoom").addEventListener( SliderEvent.CHANGE, carZoomHandler ); function carZoomHandler( e:SliderEvent ):void { camera.zoom = e.currentTarget.value - 100; doTrace( String( "camera.zoom : "+camera.zoom )); } } public function doTrace( val:String ):void { var temp:String = TextArea(this.getChildByName("traceTA")).text; temp = val + "n" + temp; TextArea(this.getChildByName("traceTA")).text = temp; } private function changeObject( _name:String ):void { removeObject(); switch (_name) { case "btn1" : cont = new DisplayObject3D(); var cube:Cube = new Cube(materialList, 100, 100, 100); var cone:Cone = new Cone(new WireframeMaterial(0xFF0000)); var sphere:Sphere = new Sphere(new WireframeMaterial(0xFF0000)); cube.x = 400; cone.z = 400; sphere.z = -100 cont.addChild( cube ); cont.addChild( cone ); cont.addChild( sphere ); scene.addChild(cont); doTrace("-------------------------"); doTrace("var cube:Cube = new Cube(materialList, 100, 100, 100);nvar cone:Cone = new Cone(new WireframeMaterial(0xFF0000));nvar sphere:Sphere = new Sphere(new WireframeMaterial(0xFF0000));"); doTrace("-------------------------"); break; case "btn2" : //Create Test test = new Test(new WireframeMaterial(0xFF0000)); scene.addChild(test); doTrace("-------------------------"); doTrace("test = new Test(new WireframeMaterial(0xFF0000));"); doTrace("-------------------------"); break; case "btn3" : //Create Collada collada = new Collada("<a href="https://sewonist.com/examples/TestObject/test.DAE">https://sewonist.com/examples/TestObject/test.DAE</a>" , materialList); scene.addChild(collada); doTrace("-------------------------"); doTrace("collada = new Collada("test.DAE" , materialList);"); doTrace("-------------------------"); break; case "btn4" : //Create DAE dae = new DAE(); dae.animate = true; dae.load("<a href="https://sewonist.com/examples/TestObject/test.DAE">https://sewonist.com/examples/TestObject/test.DAE</a>", materialList); scene.addChild(dae); doTrace("-------------------------"); doTrace("dae = new DAE();ndae.animate = true;ndae.load("test.DAE", materialList);"); doTrace("-------------------------"); break; } } private function removeObject():void { scene.removeChild( cont ); scene.removeChild( test ); scene.removeChild( collada ); scene.removeChild( dae ); } // ___________________________________________________________________ Init3D public function init3D():void { // Create viewport viewport = new Viewport3D(); addChild( viewport ); // Create Renderer renderer = new BasicRenderEngine(); // Create scene scene = new Scene3D(true); // Create Material materialList = new MaterialsList(); materialList.addMaterial( new WireframeMaterial(0xFF0000), "ColorMaterial" ); materialList.addMaterial( new WireframeMaterial(0xFF0000), "all" ); // Create camera camera = new Camera3D(); renderer.renderScene(scene, camera, viewport); } // ___________________________________________________________________ Loop public function loop(event:Event = null):void { if ( cont ) { cont.yaw(1); } if ( test ) { test.yaw(1); } if ( collada ) { collada.yaw(1); } if ( dae ) { dae.yaw(1); } renderer.renderScene(scene, camera, viewport); } } }
V. Results
위의 결과표는 매우 주관적인 견해라는 것을 꼭 기억해주기 바란다. 기본클래스를 이용한 경우에도 따로 추가해주면 맵핑과 애니메이션이 가능하다. 또 한 COLLADA를 이용하는 클래스도 사용성이 꼭 나쁘다고 할 수는 없다. 다만 위의 표는 각 방법에 대한 차이를 좀더 쉽게 이해하기 위해서 만들었으니 차이에 대해 참고 정도의 역활이었으면 한다.
확실히 플래쉬에서 구현되는 3D는 많은 제약을 가지고 있다. 특히 하드웨어 가속을 받지 않기 때문에 성능이나 기능 면에서 현란한 3D게임 같은 화면을 기대 하는 것은 무리가 있다. 하지만 날로 좋아지는 컴퓨터의 성능과 AS3의 성능 향상으로 플래쉬에서 3D를 이용한 다양한 시도가 가능 할 것으로 기대 된다. 조만간 웹에서 Coverflow 와 같은 화려한 UI 나 스페셜포스 같은 FPS 게임을 경험하게 될 지도 모른다.
VI. Links
Papervision3D : http://pv3d.org/
Collada : http://www.collada.org/mediawiki/index.php/Main_Page
ColladaMax : http://www.feelingsoftware.com/content/view/65/79/lang,en/
AS3 Geom Exporter : http://seraf.mediabox.fr/showcase/as3-geom-class-exporter-for-3ds-max-english/
ASCollada : http://ascollada.org/
오~~~~~~~~
오~~~~~~~~
안대리~~~~~
님 쫌 짱인듯
오~~~~~~~~
오~~~~~~~~
안대리~~~~~
님 쫌 짱인듯