package { import alternativa.Alternativa3D; import alternativa.engine3d.loaders.Loader3DS; import alternativa.engine3d.materials.TextureMaterialPrecision; import alternativa.engine3d.materials.WireMaterial; import alternativa.engine3d.primitives.Box; import alternativa.types.Point3D; import alternativa.utils.FPS; import com.bit101.components.Label; import com.bit101.components.PushButton; import flash.display.*; import flash.events.*; import flash.filters.*; import flash.geom.*; import flash.net.*; import flash.system.*; import jp.clockmaker.alternativa3d.BasicTemplate; import mx.graphics.codec.*; [SWF(width = 720, height = 480, frameRate = 60)] /** * @author Yasu (clockmaker.jp) */ public class Miku extends BasicTemplate { private const URL:String = "http://clockmaker.jp/labs/090807_alternativa3d/test.3ds"; [Embed(source = 'imgs/alternativa3d_big.png')] private const LOGO_IMAGE:Class; private var loader1:Loader3DS; private var loader2:Loader3DS; private var dummyBox1:Box; private var dummyBox2:Box; /** * 初期化されたときに実行されるイベントです。 * 初期化時に実行したい処理をオーバーライドして記述します。 */ override protected function atInit():void { trace(Alternativa3D.version); // 5.6 // base var base:Sprite = new Sprite(); base.graphics.beginFill(0x0); base.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight); addChildAt(base, 0); view.mouseChildren = false; // マウスイベントの透過 view.mouseEnabled = false; // load var context:LoaderContext = new LoaderContext(true); // ミクを二つ作る loader1 = new Loader3DS(); loader1.addEventListener(Event.COMPLETE, onLoadHandler); loader1.load(URL, context); loader2 = new Loader3DS(); loader2.addEventListener(Event.COMPLETE, onLoadHandler); loader2.load(URL, context); // ドラッグ時の処理が重いので、ドラッグ時はダミーのワイヤーフレームに差し替える var mat:WireMaterial = new WireMaterial(1, 0x808080); dummyBox1 = new Box(300, 300, 400, 3, 3, 4); dummyBox1.cloneMaterialToAllSurfaces(mat); dummyBox1.x = 300; dummyBox2 = new Box(300, 300, 400, 3, 3, 4); dummyBox2.cloneMaterialToAllSurfaces(mat); dummyBox2.x = -300; // FPS display launch FPS.init(stage); // mouse interactive base.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown); // licence addChild(new LOGO_IMAGE); // Button new PushButton(this, 10, 100, "Capture Photo", capture); new Label(this, 20, 80, "Please Drag Stage"); } private function onLoadHandler(e:Event):void { var l:Loader3DS = e.target as Loader3DS; scene.root.addChild(l.content); l.content.scaleX = l.content.scaleY = l.content.scaleZ = 20; l.precision = TextureMaterialPrecision.NONE; // more performance ? switch(l) { case loader1: l.content.x = 300; l.content.rotationZ = -Math.PI / 2; break; case loader2: l.content.x = -300; l.content.rotationZ = Math.PI / 2; break; } } /** * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。 * レンダリング前に実行したい処理をオーバーライドして記述します。 */ override protected function atPreRender():void { // Mouse Interactive camera.x = 500 * Math.sin(cameraYaw * Math.PI / 180); camera.y = 500 * Math.cos(cameraYaw * Math.PI / 180); camera.z = cameraPitch; cameraContoller.lookAt(new Point3D(0, 0, 0)); } // ---------------------------------------------- // Mouse Interactive // ---------------------------------------------- private var isOribiting:Boolean; private var cameraPitch:Number = 200; private var cameraYaw:Number = 180; private var previousMouseX:Number; private var previousMouseY:Number; private function onMouseDown(event:MouseEvent):void { isOribiting = true; previousMouseX = event.stageX; previousMouseY = event.stageY; stage.quality = StageQuality.MEDIUM; scene.root.removeChild(loader1.content); scene.root.removeChild(loader2.content); scene.root.addChild(dummyBox1); scene.root.addChild(dummyBox2); stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); } private function onMouseUp(event:MouseEvent):void { isOribiting = false; stage.quality = StageQuality.HIGH; scene.root.addChild(loader1.content); scene.root.addChild(loader2.content); scene.root.removeChild(dummyBox1); scene.root.removeChild(dummyBox2); stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp); } private function onMouseMove(event:MouseEvent):void { var differenceX:Number = event.stageX - previousMouseX; var differenceY:Number = event.stageY - previousMouseY; if(isOribiting) { cameraPitch += differenceY * 2; cameraYaw += differenceX * 0.25; previousMouseX = event.stageX; previousMouseY = event.stageY; } } // ---------------------------------------------- // Capture // ---------------------------------------------- private function capture(e:Event):void{ var o:Point3D = new Point3D(camera.x, camera.y, camera.z); var bd1:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0x00000000); bd1.draw(view); scene.root.removeChild(loader1.content); var bds:Vector. = new Vector.(); for (var i:int = 0; i < 10; i++) { camera.coords = getRandomPos(o); scene.calculate(); var bd:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, true, 0x00000000); bd.draw(view); //bd.applyFilter(bd, bd.rect, new Point, new BlurFilter(2, 2, 1)); bds.push(bd); } bds.fixed = true; // make pictur var master:BitmapData = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0xFF000000); master.lock(); master.copyPixels(bd1, bd1.rect, new Point()); for (i = 0; i < bds.length; i++) { master.copyPixels(bds[i], bds[i].rect, new Point(), new BitmapData(stage.stageWidth, stage.stageHeight, true, 0x20000000), new Point, true); } master.unlock(); var enc:PNGEncoder = new PNGEncoder(); var fileRef:FileReference = new FileReference(); fileRef.save(enc.encode(master), "capture.png"); // reset camera.coords = o; scene.root.addChild(loader1.content); } private function getRandomPos(o:Point3D):Point3D { var len:Number = 15; return new Point3D( o.x + len * (Math.random() - 0.5), o.y + len * (Math.random() - 0.5), o.z + len * (Math.random() - 0.5) ); } } }