[FlashPlayer10]TweenerでTumblr3Dギャラリー

Tags: ,

元ネタはFlash Player 10 Beta: 3D(注:動画)。これ中々面白いからFlash Player 10を使わずに作って展示したいんだけど、z軸方向をどう扱うのかが問題。普通にリサイズすれば同じ動きになるんだろうか。クリックで各画像にフォーカス、ダブルクリックでその画像のPermalinkへ飛びます。

[FLASH10]Tumblr Spiral
[FLASH10]Tumblr Spiral (要Flash Plaeyer 10)

以下ソース。テキストフィールド等の装飾品は除いています。

Main.as (メインクラス)

package {
    /*
    * Requires Flex SDK 3.0.1 or later to be compiled
    */
    import caurina.transitions.Tweener;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.net.URLLoader;
    import flash.net.URLRequest;

    [SWF(width="550",height="400",backgroundColor="0×0",frameRate="24")]

    public class Main extends Sprite{
        //Setting for Tumblr API
        private const IMG_SIZE:int = 75;
        private const USERID:String = "borealkiss";
        private const QUERY_NUM:int = 30;

        //Canvas
        private var container:Sprite;

        public function Main(){
            container = new Sprite();
            container.x = stage.stageWidth/2;
            container.y = stage.stageHeight/2;
            addChild(container);

            //Query string for Tumblr API
            var str:String = "http://"+USERID+".tumblr.com/api/read?num="
                                +QUERY_NUM+"&type=photo";
            var loader:URLLoader = new URLLoader();
            loader.load(new URLRequest(str));
            loader.addEventListener(Event.COMPLETE,parseXML);
        }

        //XML parser
        public function parseXML(e:Event):void{
            var xmlData:XML = new XML(e.target.data);
            var imgURLs:Array = new Array();
            var postURLs:Array = new Array();

            for each (var ch1:XML in xmlData.posts.post){
                var postURL:String = ch1.attribute("url").toString();
                postURLs.push(postURL);
                for each (var ch2:XML in ch1.child("photo-url")){
                    if (ch2.attribute("max-width") == IMG_SIZE){
                        var imgURL:String = ch2.toString();
                        imgURLs.push(imgURL);
                    }
                }
            }
            makeFaces(imgURLs,postURLs,true);
        }

        private function makeFaces(aryImgURLs:Array,aryPostURLs:Array,
                                    flgNavigate:Boolean):void{

            //Radius of a spiral
            const RAD:Number = 250;

            for (var i:uint=0; i<aryImgURLs.length; i++){
                var f:FaceDoubleClick = new FaceDoubleClick(
                            aryImgURLs[i],aryPostURLs[i],flgNavigate);

                //Set photos along the spiral
                f.x = RAD*Math.cos(i*Math.PI/6);
                f.y = RAD*Math.sin(i*Math.PI/6);
                f.z = (aryImgURLs.length-i)*200;
                f.buttonMode = true;
                f.addEventListener(MouseEvent.CLICK,onClick);
                container.addChild(f);
            }
        }

        private function onClick(e:MouseEvent):void{
            //Must be tuned upon image size
            var offsetX:Number = 270;
            var offsetY:Number = 190;
            var offsetZ:Number = 0;

            var sp:Sprite = Sprite(e.target);
            Tweener.addTween(container,{x:-sp.x+offsetX, y:-sp.y+offsetY,
                                        z:-sp.z+offsetZ, time:1});
        }
    }
}

FaceDoubleClick.as

package{
    import flash.display.Bitmap;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.net.URLRequest;
    import flash.net.navigateToURL;
    import flash.system.LoaderContext;

    public class FaceDoubleClick extends Sprite{
        private var _url:String;
        private var _loader:Loader;
        private var flgNavigate:Boolean;

        public function FaceDoubleClick(imgURL:String,postURL:String = "null",
                                                flgNavigate:Boolean = false){
            _url = postURL;
            this.flgNavigate = flgNavigate;

            var context:LoaderContext = new LoaderContext(true);
            _loader = new Loader();
            _loader.load(new URLRequest(imgURL), context);
            _loader.contentLoaderInfo.addEventListener(Event.INIT,init);

            this.doubleClickEnabled = true;
            addEventListener(MouseEvent.DOUBLE_CLICK, doubleClick);
        }

        private function init(e:Event):void{
            //The image center will be placed on center
            var bmp:Bitmap = Bitmap(e.target.content);
            bmp.x = -bmp.width/2;
            bmp.y = -bmp.height/2;
            addChild(bmp);
        }

        private function doubleClick(e:MouseEvent):void{
            if (flgNavigate){
                navigateToURL(new URLRequest(_url));
            }
        }
    }
}

Flex Builder 3でFlash Player 10のデバッグ機能を使用する方法

Tags: ,

  1. Flash Player 10 単体版をこちらからダウンロード。現在のところオフィシャルには配布されていない様子。

    [追記:2008/06/01] 3/16以降のFlex SDK Nightly Buildに含まれているようです(akihiro kamijo: Flash Player 10 ベータのデバッグプレーヤ)
  2. SWFファイルを(常時)このプレイヤーで開くように関連づける。Macの場合swfファイルを右クリック > 情報を見る > このアプリケーションで開く > Flash Player 10を選択
  3. 実際にFlex Builder 3でActionScriptプロジェクトを作成
  4. 作成したプロジェクトのプロパティ > 実行/デバッグの設定 > 現在のプロジェクトを選択して編集(なければ新規作成)
  5. 起動するURLまたはパス > 「デフォルトを使用する」のチェックをはずす
  6. デバッグの項の起動パスをswfファイルそのものに変更(bin-debug/****.swf)して設定適用
  7. 実際にデバッグを起動すると「現在のバージョンでデバッグを試みますか?」と聞かれるので「はい」を選択

これでswfファイルを起動するFlash Playerが先ほどダンロードしたFlash Player 10に設定されているならデバッグが機能するはず。情報元はTargeting Flash Player 10 Beta with Flex SDK 3.0.x - Flex SDK - Confluenceのコメント欄より。

[FlashPlayer10]drawRectanglesでパノラマ画像をテクスチャリング

Tags:

円環状の多面体(長方形が複数繋がったようなやつ。各長方形は三角形二つで構成)に沿ってパノラマ画像を貼付け。胆はテクスチャ貼付け用のUVT座標の設定と、円環の内側が見えるようcullingしたこと。z-sortはなんにもしてない。あと、今回新しく追加されたVector3DクラスをPointクラスの3Dバージョン(x,y,z)ではないかと推測して使っているので正しい使い方ではないかも。

[追記2008/05/19]
Vector3Dの説明やプリミティブ図形の描画方法を説明している記事発見。かなり参考になる。

[FLASH10]パノラマ
[FLASH10]パノラマ (要Flash Plaeyer 10)

package {
    /*
    * Requires Flex SDK 3.0.1 or later to be compiled
    */
    import __AS3__.vec.Vector;
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.display.TriangleCulling;
    import flash.events.Event;
    import flash.geom.Vector3D;

    [SWF(width="700",height="400",backgroundColor="0×0",frameRate="24")]

    public class Astro11 extends Sprite{
        [Embed(source="img/panoramic.jpg")]
        private var TestImage:Class;

        private var img:Bitmap;
        private var container:Sprite;

        public function Astro11(){
            //Canvas
            container = new Sprite();
            container.x = stage.stageWidth/2;
            container.y = stage.stageHeight/2;
            addChild(container);

            img = new TestImage();
            addEventListener(Event.ENTER_FRAME,rotate);
        }

        private function rotate(e:Event):void{
            const DUMP:Number = 2.5e-3;
            var dx:Number = (mouseX - stage.stageWidth/2);
            drawScene(dx*DUMP);
        }

        private function drawScene(angle:Number):void{
            container.graphics.clear();

            //Total number of rectangle faces along a torus, 
            //i.e., 2xTOTAL triangles.
            const TOTAL:int = 30;

            //Radius of the torus
            const R:Number = 200;

            //Focal length
            const F:Number = 200;

            //Angular offset of the image 
            //for hiding the image’s "non-gapless edge"
            const OFFSET:Number = -Math.PI/2;
            angle += OFFSET;

            //Size of a rectangle that two triangles make
            var w:Number = 2*Math.PI*R/TOTAL;
            var h:Number = img.height;

            //Arguments for drawRectangles
            var vertices:Vector.<Number> = new Vector.<Number>();
            var indices:Vector.<int> = new Vector.<int>();
            var uvtData:Vector.<Number> = new Vector.<Number>();

            for (var i:int=0; i<TOTAL; i++){
                var dt:Number = 2*Math.PI/TOTAL;

                indices.push(2*i,2*(i+1),2*i+1, 2*i+1,2*(i+1),2*(i+1)+1);

                if (i==0){
                    //Define the position of each vertex in 3D space
                    var v0:Vector3D = new Vector3D(R*Math.cos(angle+i*dt),
                                                -h/2,R*Math.sin(angle+i*dt));
                    var v1:Vector3D = new Vector3D(R*Math.cos(angle+i*dt),
                                                h/2,R*Math.sin(angle+i*dt));
                    var v2:Vector3D = new Vector3D(R*Math.cos(angle+(i+1)*dt),
                                                -h/2,R*Math.sin(angle+(i+1)*dt));
                    var v3:Vector3D = new Vector3D(R*Math.cos(angle+(i+1)*dt),
                                                h/2,R*Math.sin(angle+(i+1)*dt));

                    //Scaling factor
                    var t0:Number = F/(F + v0.z);
                    var t1:Number = F/(F + v1.z);
                    var t2:Number = F/(F + v2.z);
                    var t3:Number = F/(F + v3.z);

                    vertices.push(v0.x*t0,v0.y*t0, v1.x*t1,v1.y*t1,
                                    v2.x*t2,v2.y*t2, v3.x*t3,v3.y*t3);
                    uvtData.push(i/TOTAL,i/TOTAL,t0, i/TOTAL,1,t1,
                                    (i+1)/TOTAL,0,t2, (i+1)/TOTAL,1,t3);
                }
                else{
                    v2 = new Vector3D(R*Math.cos(angle+(i+1)*dt),
                                                -h/2,R*Math.sin(angle+(i+1)*dt));
                    v3 = new Vector3D(R*Math.cos(angle+(i+1)*dt),
                                                h/2,R*Math.sin(angle+(i+1)*dt));

                    t2 = F/(F + v2.z);
                    t3 = F/(F + v3.z);

                    vertices.push(v2.x*t2,v2.y*t2, v3.x*t3,v3.y*t3);
                    uvtData.push((i+1)/TOTAL,0,t2, (i+1)/TOTAL,1,t3);
                }
            }

            //Frontface culling
            container.graphics.beginBitmapFill(img.bitmapData);
            container.graphics.drawTriangles(vertices,indices,uvtData,
                                            TriangleCulling.POSITIVE);
            container.graphics.endFill();
        }
    }
}

[FlashPlayer10]お尻プルルン

Tags:

Flash Player 10で新しく使えるようになったグラフィックメソッドのdrawTrianglesを使ってみた。まだ完全に理解してないのだけど、このメソッドでおそらくポリゴン表面に画像貼付けたりできるようになると思う。画像歪ませるのが簡単になった。

[FLASH 10]お尻プルルン
[FLASH 10]お尻プルルン (要Flash Plaeyer 10)

ソース。

package {
    /*
    * Requires Flex SDK 3.0.1 or later to be compiled
    */
    import __AS3__.vec.Vector;
    import flash.display.Bitmap;
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Point;

    [SWF(width="550",height="400",backgroundColor="0×0",frameRate="24")]

    public class Astro08 extends Sprite{
        [Embed(source="img/girl.jpg")]
        private var TestImage:Class;

        private var img:Bitmap;
        private var container:Sprite;

        //true for mouse down, otherwise false.
        private var flgMouseDown:Boolean;

        //true for mouse rollover, otherwise false.
        private var flgMouseOver:Boolean;

        //drawTriangles
        private var vertices:Vector.<Number>;
        private var indices:Vector.<int>;
        private var uvts:Vector.<Number>;

        //The origin of springing motion
        private var initP:Point;

        //Velocities of springing motion
        private var velocities:Vector.<Number> = Vector.<Number>([0,0]);

        public function Astro08(){
            img = new TestImage();
            initImage(img.width*0.5,img.height*0.5);

            container.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDown);
            container.addEventListener(MouseEvent.MOUSE_UP,onMouseUp);
            container.addEventListener(MouseEvent.MOUSE_OVER, onRollOver);
            container.addEventListener(MouseEvent.MOUSE_OUT, onRollOut);
            addEventListener(Event.ENTER_FRAME,onEnterFrame);
        }

        private function initImage(w:Number,h:Number):void{
            initP = new Point(w/2,h/2);
            vertices = Vector.<Number>([0,0, w,0, initP.x,initP.y, w,h, 0,h]);
            indices = Vector.<int>([0,1,2, 1,3,2, 2,3,4, 2,4,0]);
            uvts = Vector.<Number>([0,0, 1,0, 1/2,1/2, 1,1, 0,1]);

            //Canvas
            container = new Sprite();
            container.x = stage.stageWidth/2 - w/2;
            container.y = stage.stageHeight/2 - h/2;
            addChild(container);

            container.graphics.beginBitmapFill(img.bitmapData);
            container.graphics.drawTriangles(vertices,indices,uvts);
        }

        private function onEnterFrame(e:Event):void{
            const SPRING:Number = 0.9;
            const FRICTION:Number = 0.8;

            container.graphics.clear();

            if(flgMouseDown && flgMouseOver){
                vertices[4] = container.mouseX;
                vertices[5] = container.mouseY;
            }
            else{
                //Springing motion
                var dx:Number = initP.x - vertices[4];
                var ax:Number = dx*SPRING;
                velocities[0] += ax;
                velocities[0] *= FRICTION;
                vertices[4] += velocities[0];

                var dy:Number = initP.y - vertices[5];
                var ay:Number = dy*SPRING;
                velocities[1] += ay;
                velocities[1] *= FRICTION;
                vertices[5] += velocities[1];
            }

            container.graphics.beginBitmapFill(img.bitmapData);
            container.graphics.drawTriangles(vertices,indices,uvts);
        }

        private function onMouseDown(e:MouseEvent):void{
            flgMouseDown = true;
        }

        private function onMouseUp(e:MouseEvent):void{
            flgMouseDown = false;
        }

        private function onRollOver(e:MouseEvent):void{
            flgMouseOver = true;
        }

        private function onRollOut(e:MouseEvent):void{
            flgMouseOver = false;
        }
    }
}

[FlashPlayer10]My First Astro

Tags:

数日前にFlash Player 10(Astro)のベータ版が発表されて新機能や新クラスの話題でFlash界隈は盛り上がってるみたい。DisplayObjectのプロパティに新しくz軸が追加されて3D描画が可能になった。とはいっても今まで自分で設定しなくちゃいけなかった焦点距離の計算が省けただけなのかな?単純にdrawRect()するだけではdepth sortingやbackface cullingまではしてくれないみたい。僕も色々調べ中。とりあえずFlash Player 10 で 3Dしてみた (Unknown Quality)を参考に3Dやってみた。参考元はFlex SDK 3.0.1より前のものを使用しているのでパブリッシュに色々トリック(astro::って部分等)を使ってるみたいだけど、現在はFlash Player 10用にパブリッシュできるFlex SDK 3.0.1.xが配布されているので気にしなくてよい。

[FLASH 10]My First Astro
[FLASH 10]My First Astro (再生にはFlash Plaeyer 10が必要)

[関連リンク]

一応ソースコード。rotationXとかあるよね。

package {
    /*
    * Requires Flex SDK 3.0.1.x to be compiled
    */
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.events.Event;

    [SWF(width="550",height="400",backgroundColor="0×0")]

    public class Main extends Sprite{

        //size of the box
        private const SIZE:Number = 100;

        public function Main(){
            var spr:Sprite = new Sprite();
            spr.x = stage.stageWidth/2;
            spr.y = stage.stageHeight/2;
            addChild(spr);
            makeCube(spr,0x005885);
            spr.addEventListener(Event.ENTER_FRAME,rotate);
        }

        private function makeCube(s:Sprite,c:uint):void{
            //front
            var f1:Shape = new Shape();
            f1.graphics.lineStyle(2,c);
            f1.graphics.drawRect(0,0,SIZE,SIZE);
            f1.x = -SIZE/2;
            f1.y = -SIZE/2;
            f1.z = -SIZE/2;
            s.addChild(f1);

            //back
            var f2:Shape = new Shape();
            f2.graphics.lineStyle(2,c);
            f2.graphics.drawRect(0,0,SIZE,SIZE);
            f2.x = -SIZE/2;
            f2.y = -SIZE/2;
            f2.z = SIZE/2;
            s.addChild(f2);

            //left
            var f3:Shape = new Shape();
            f3.graphics.lineStyle(2,c);
            f3.graphics.drawRect(0,0,SIZE,SIZE);
            f3.rotationY = 90;
            f3.x = -SIZE/2;
            f3.y = -SIZE/2;
            f3.z = SIZE/2;
            s.addChild(f3);

            //right
            var f4:Shape = new Shape();
            f4.graphics.lineStyle(2,c);
            f4.graphics.drawRect(0,0,SIZE,SIZE);
            f4.rotationY = 90;
            f4.x = SIZE/2;
            f4.y = -SIZE/2;
            f4.z = SIZE/2;
            s.addChild(f4);

            //top
            var f5:Shape = new Shape();
            f5.graphics.lineStyle(2,c);
            f5.graphics.drawRect(0,0,SIZE,SIZE);
            f5.rotationX = 90;
            f5.x = -SIZE/2;
            f5.y = -SIZE/2;
            f5.z = -SIZE/2;
            s.addChild(f5);

            //bottom
            var f6:Shape = new Shape();
            f6.graphics.lineStyle(2,c);
            f6.graphics.drawRect(0,0,SIZE,SIZE);
            f6.rotationX = 90;
            f6.x = -SIZE/2;
            f6.y = SIZE/2;
            f6.z = -SIZE/2;
            s.addChild(f6);
        }

        private function rotate(e:Event):void{
            const DUMP:Number = 0.25;
            var dx:Number = (mouseX - stage.stageWidth/2);
            var dy:Number = (mouseY - stage.stageHeight/2);
            e.target.rotationY = -dx*DUMP;
            e.target.rotationX = dy*DUMP;
        }
    }
}

← Previous PageNext Page →