Beautifl - Flash Gallery

Thumbnail : Alternativa3D Tips 読み込んだ、3DSモデルの中身を操作する
Alternativa3D Tips 読み込んだ、3DSモデルの中身を操作する
narutohyper 2010-01-11 MIT License

再生するにはFlash Playerが必要です。デスクトップのブラウザでご覧ください。

// forked from clockmaker's [Alternativa3D] Negi Miku
package {
    import alternativ5.engine3d.materials.FillMaterial;
    import alternativ5.engine3d.primitives.Plane;
    import alternativ5.engine3d.primitives.Cone;
    import alternativ5.engine3d.core.Object3D;
    import alternativ5.engine3d.core.Mesh;
    import alternativ5.engine3d.events.MouseEvent3D
    import alternativ5.engine3d.loaders.*; 
    import alternativ5.types.Point3D;
    import alternativ5.types.Texture;
    import alternativ5.utils.*

    import flash.system.LoaderContext; 
    import flash.display.StageQuality;
    import flash.display.Sprite;
    import flash.display.BlendMode;
    import flash.display.BitmapData;
    import flash.display.Bitmap;
    import flash.display.GradientType;
    import flash.events.MouseEvent;
    import flash.events.Event;
    import flash.utils.getDefinitionByName;

    import flash.text.*;

    import flash.geom.Matrix;
    import flash.utils.*;
    

    [SWF(width = 465, height = 465, frameRate = 60,backgroundColor=0x000000)]
    /**
     * Alternativa3D Tips 読み込んだ、3DSモデルの中身を操作する
     * 
     * Clickで、腕振ります
     * BetweenとかTweener使えば、滑らかに動かせますが、中身を操作するTIPSなので、そのあたりは適当です。
     * 
     * folk元は、まだalternativa template前の物でしたので、templateに移植してます。
     * 
     * @narutohyper
    */

     /** 
     * Alternativa3D で3Dモデルを読み込むテスト 
     * マウスドラッグでミクを回せます 
     *  
     * ライブラリでサポートしているファイルは「3DS」と「OBJ」(Colladaは対応していない) 
     * このサンプルでは3dsファイルを読み込んでいます 
     *  
     * 3Dデータはnote.xさんのところのズサさんご提供のものを使用しています。 
     * http://blog.r3c7.net/?p=121 
     * ※ColladaファイルをBlenderで3DSファイルに変換したものを使用 
     * ↑ 
     * この記事のデモと速度や表示を比較してみるといいかも 
     */ 
    public class SimpleDemo extends Sprite {

        
        public function SimpleDemo():void {
            // テンプレートを作成します
            var template:BasicTemplate = new BasicTemplate();
            addChild(template);
            template.camera.z = -500;

            // FPS display launch 
            FPS.init(stage); 

            var dbg:TextField=new TextField()
            dbg.autoSize=TextFieldAutoSize.LEFT
            dbg.selectable=false;
            dbg.mouseEnabled=false;
            var format:TextFormat=new TextFormat();
            format.color=0x666666
            format.size=12;
            format.font='_ゴシック';
            dbg.defaultTextFormat=format
            this.addChild(dbg)

            var context:LoaderContext = new LoaderContext(); 
            var loader:Loader3DS = new Loader3DS(); 
            loader.addEventListener(Event.COMPLETE, loadCompleteHandler); 
            loader.load("http://clockmaker.jp/labs/090807_alternativa3d/test.3ds", context); 
            var lm:Object3D;
            var rarm:Mesh
            var negi:Mesh
            var near:Mesh
            var far:Mesh

            function loadCompleteHandler(e:Event):void {
            
                template.scene.root.addChild(loader.content);
                loader.content.scaleX = loader.content.scaleY = loader.content.scaleZ = 20;

                lm=loader.content

                //読み込んだ3ds(Object3D)の子Objectにはnameがわかれば個別にアクセスできるようになります
                //自分で作成したモデルなどでは、問題ありませんが、もし名前等がわからない場合は
                //以下のような方法で調べます

                //メソッド[Object3D.forEach()]ですべての子Object3Dにアクセスできます

                lm.forEach(test)
                function test():void {
                    //traceで('R_arm'、'negi'、'miku_near'、'miku_far'という名前のMeshが確認できます)
                    //ついでに、3dsモデルのゴミ掃除をします
                    if(this is Mesh) {
                        //trace('掃除前',this.name,this);
                        dbg.appendText('掃除前 '+this.name+' '+this+'\n')

                        //サーフェースに属していないFacsを削除します。
                        MeshUtils.removeSingularFaces(Mesh(this));
                        //直線上に存在する、Faceの頂点になっていない点を削除します
                        MeshUtils.removeUselessVertices(Mesh(this));
                        //使われていない、孤立した点を削除します
                        MeshUtils.removeIsolatedVertices(Mesh(this));
                        //同じ座標で複数存在する点を、一つにまとめます
                        MeshUtils.autoWeldVertices(Mesh(this), 0.01);
                        //重なっている、面を統合します。
                        MeshUtils.autoWeldFaces(Mesh(this), 0.01, 0.001);

                        //trace('掃除後',this.name,this);
                        dbg.appendText('掃除後 '+this.name+' '+this+'\n')
                    }
                }

                //名前がわかれば、Object3D.getChildByNameでアクセスできます。
                rarm=Mesh(lm.getChildByName('R_arm'));
                negi=Mesh(lm.getChildByName('negi'));
                near=Mesh(lm.getChildByName('miku_near'));
                far =Mesh(lm.getChildByName('miku_far'));

                var angle:Number=0

                //lm.rotationX=MathUtils.toRadian(90);

                    rarm.rotationX += 10 * Math.PI / 180;
                    negi.rotationX += 10 * Math.PI / 180;

                //毎Frame毎のレンダリングを中止
                template.stopRendering()

                stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
                stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
                stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);

                // ----------------------------------------------
                // Mouse Interactive 
                // ----------------------------------------------
                var isOribiting:Boolean;
                var cameraPitch:Number = 200;
                var cameraYaw:Number = 180;
                var previousMouseX:Number;
                var previousMouseY:Number;

                rarm.rotationX = MathUtils.toRadian(0);
                negi.rotationX = MathUtils.toRadian(0);
                singleRender(null);


                function onMouseDown(event:MouseEvent=null):void {
                    isOribiting = true;
                    previousMouseX = event.stageX;
                    previousMouseY = event.stageY;

                    rarm.rotationX = MathUtils.toRadian(20);
                    negi.rotationX = MathUtils.toRadian(20);
                    rarm.rotationZ = MathUtils.toRadian(0);
                    negi.rotationZ = MathUtils.toRadian(0);
                    rarm.y=0.05;
                    negi.y=0.05;
                    rarm.z=0.2;
                    negi.z=0.2;

                    singleRender(null);
                }

                function onMouseUp(event:MouseEvent=null):void {
                    isOribiting = false;
                    stage.quality = StageQuality.HIGH;

                    rarm.rotationX = MathUtils.toRadian(0);
                    negi.rotationX = MathUtils.toRadian(0);
                    rarm.rotationZ = MathUtils.toRadian(0);
                    negi.rotationZ = MathUtils.toRadian(0);
                    rarm.y=0;
                    negi.y=0;
                    rarm.z=0;
                    negi.z=0;
                    singleRender(null);
                }

                function onMouseMove(event:MouseEvent=null):void {
                    var differenceX:Number = event.stageX - previousMouseX;
                    var differenceY:Number = event.stageY - previousMouseY;

                    if(isOribiting) {
                        //stage.quality = StageQuality.MEDIUM;
                        cameraPitch += differenceY;
                        cameraYaw += differenceX * 0.25;

                        previousMouseX = event.stageX;
                        previousMouseY = event.stageY;

                        singleRender(null);
                    }
                }


                function singleRender(e:Event):void 
                {
                    // Mouse Interactive 
                    template.camera.x = 500 * Math.sin(cameraYaw * Math.PI / 180);
                    template.camera.y = 500 * Math.cos(cameraYaw * Math.PI / 180);
                    template.camera.z = cameraPitch;

                    template.cameraContoller.lookAt(new Point3D());

                    // Scene calculating 
                    template.singleRender()
                }


            }




        }



    }
}






import alternativ5.engine3d.controllers.CameraController;
import alternativ5.engine3d.core.Camera3D;
import alternativ5.engine3d.core.Object3D;
import alternativ5.engine3d.core.Scene3D;
import alternativ5.engine3d.display.View;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageQuality;
import flash.display.StageScaleMode;
import flash.events.Event;


/**
 * BasicTemplate for Alternativa3D
 * Alternativa3Dを扱いやすくするためのテンプレートです
 * @author Yasu
 */
class BasicTemplate extends Sprite{
    /**
     * シーンインスタンスです。
     */
    public var scene:Scene3D;
    /**
     * ビューインスタンスです。
     */
    public var view:View;
    /**
     * カメラインスタンスです。
     */
    public var camera:Camera3D;
    /**
     * カメラコントローラーです。
     */
    public var cameraContoller:CameraController;
    
    private var _viewWidth:int;
    private var _viewHeight:int;
    private var _scaleToStage:Boolean;

    /**
     * 新しい BasicTemplate インスタンスを作成します。
     * @param    viewWidth
     * @param    viewHeight
     * @param    scaleToStage
     */
    public function BasicTemplate(viewWidth:int=640, viewHeight:int=480, scaleToStage:Boolean = true) {
        _viewWidth = viewWidth;
        _viewHeight = viewHeight;
        _scaleToStage = scaleToStage;
        
        // Creating scene
        scene = new Scene3D();
        scene.splitAnalysis = false; // not analysis for performance
        scene.root = new Object3D();
        
        // Adding camera
        camera = new Camera3D();
        camera.z = -1000;
        scene.root.addChild(camera);
        
        // camera contoller
        cameraContoller = new CameraController(this);
        cameraContoller.camera = camera;
        
        // set view
        view = new View();
        view.camera = camera;
        addChild(view);
        
        // stage
        if (stage) init();
        else addEventListener(Event.ADDED_TO_STAGE, init);
    }
    
    /**
     * 初期化されたときに実行されるイベントです。
     * 初期化時に実行したい処理をオーバーライドして記述します。
     */
    protected function atInit():void {}
    
    /**
     * 初期化されたときに実行されるイベントです。
     * 初期化時に実行したい処理を記述します。
     */
    private var _onInit:Function = function():void { };
    public function get onInit():Function { return _onInit; }
    public function set onInit(value:Function):void {
        _onInit = value;
    }
    
    /**
     * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
     * レンダリング前に実行したい処理をオーバーライドして記述します。
     */
    protected function atPreRender():void {}
    
    /**
     * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
     * レンダリング前に実行したい処理を記述します。
     */
    private var _onPreRender:Function = function():void{};
    public function get onPreRender():Function { return _onPreRender; }
    public function set onPreRender(value:Function):void {
        _onPreRender = value;
    }
    
    /**
     * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
     * レンダリング後に実行したい処理をオーバーライドして記述します。
     */
    protected function atPostRender():void {
    }
    
    /**
     * Event.ENTER_FRAME 時に実行されるレンダリングのイベントです。
     * レンダリング後に実行したい処理を記述します。
     */
    protected var _onPostRender:Function = function():void{};
    public function get onPostRender():Function { return _onPostRender; }
    public function set onPostRender(value:Function):void {
        _onPostRender = value;
    }
    
    /**
     * レンダリングを開始します。
     */
    public function startRendering():void {
        addEventListener(Event.ENTER_FRAME, onRenderTick);
    }
    /**
     * レンダリングを停止します。
     */
    public function stopRendering():void {
        removeEventListener(Event.ENTER_FRAME, onRenderTick);
    }
    
    /**
     * シングルレンダリング(レンダリングを一回だけ)を実行します。
     */
    public function singleRender():void {
        onRenderTick();
    }
    
    /**
     * @private
     */
    private function init(e:Event = null):void {
        stage.scaleMode = StageScaleMode.NO_SCALE;
        stage.align = StageAlign.TOP_LEFT;
        stage.quality = StageQuality.HIGH;

        // resize
        stage.addEventListener(Event.RESIZE, onResize);
        onResize(null);
        
        // render
        startRendering();
        
        atInit();
        _onInit();
        
    }
    
    /**
     * @private
     */
    private function onRenderTick(e:Event = null):void {
        atPostRender();
        _onPostRender();
        scene.calculate();
        atPreRender();
        _onPreRender();
    }
    
    /**
     * @private
     */
    private function onResize(event:Event = null):void {
        if (_scaleToStage) {
            view.width = stage.stageWidth;
            view.height = stage.stageHeight;
        }else {
            view.width = _viewWidth;
            view.height = _viewHeight;
        }
    }
}