Beautifl - Flash Gallery

Thumbnail : [1日1Wonderfl]2日目: Papervision3D で惑星まみれ
[1日1Wonderfl]2日目: Papervision3D で惑星まみれ
soundkitchen 2009-11-27 All rights reserved

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

// forked from soundkitchen's [1日1Wonderfl]1日目: Papervision3D でボールまみれ
// 1日1Wonderfl 2/30日目
package
{
    import flash.display.BitmapData;
    import flash.display.BitmapDataChannel;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.filters.BitmapFilter;
    import flash.filters.BitmapFilterQuality;
    import flash.filters.ColorMatrixFilter;
    import flash.filters.GlowFilter;
    import flash.geom.Point;

    import com.flashdynamix.utils.SWFProfiler;

    import org.papervision3d.cameras.Camera3D;
    import org.papervision3d.lights.PointLight3D;
    import org.papervision3d.materials.BitmapMaterial;
    import org.papervision3d.materials.ColorMaterial;
    import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
    import org.papervision3d.objects.DisplayObject3D;
    import org.papervision3d.objects.primitives.Sphere;
    import org.papervision3d.render.BasicRenderEngine;
    import org.papervision3d.scenes.Scene3D;
    import org.papervision3d.view.Viewport3D;

    [SWF(width=465, height=465, frameRate=30, backgroundColor=0x000000)]

    /**
     *  最近のトレンドが FLARToolKit になりつつあるので、
     *  そこに向かうために、とりあえずは Papervision3D を、
     *  無駄なく無理なく軽いタッチで使えるようになりたい。
     */
    public class Main extends Sprite
    {
        public static const NUM_SPHERES:uint = 15;

        private var camera:Camera3D;
        private var light:PointLight3D;
        private var renderer:BasicRenderEngine;
        private var scene:Scene3D;
        private var viewport:Viewport3D;

        private var root3d:DisplayObject3D;

        /**
         *  コンストラクタ
         */
        public function Main()
        {
            //  ステージ上で会いましょう
            addEventListener(Event.ADDED_TO_STAGE, initialize);
        }

        /**
         *  オブジェクトの初期化
         */
        private function initialize(evt:Event):void
        {
            //  要らなくなったイベントは外す
            removeEventListener(Event.ADDED_TO_STAGE, initialize);

            //  ステージの設定
            stage.align = StageAlign.TOP_LEFT;
            stage.quality = StageQuality.MEDIUM;
            stage.scaleMode = StageScaleMode.NO_SCALE;

            //  SWFProfiler 仕込む
            SWFProfiler.init(this);

            //  Papervision3D の初期化
            setupPV3D();

            //  root の Papervision3D 版みたいなノリ
            root3d = new DisplayObject3D();
            scene.addChild(root3d, 'root');

            var l:uint,
                r:int, g:int, b:int,
                hc:uint, dc:uint,
                seedBmd:BitmapData,
                bmd:BitmapData,
                cmf:ColorMatrixFilter,
                zp:Point,
                //material:FlatShadeMaterial,
                material:BitmapMaterial,
                sphere:Sphere;

            //  ゼロポイント
            zp = new Point();
            //  元となるデータを作る
            seedBmd = new BitmapData(80, 80, true, 0);
            seedBmd.perlinNoise(20, 20, 8, 10, true, true, BitmapDataChannel.RED, true);

            //  指定個数だけボールを作る
            l = NUM_SPHERES;
            while (l--)
            {
                //  適当に色を作ります
                r = 0xff * Math.random();
                g = 0xff * Math.random();
                b = 0xff * Math.random();

                /**
                 *  FIXME:
                 *      グレイスケールで生成した BitmapData に対して、
                 *      上で適当に生成した色を適応させるための方法として、
                 *      下のような ColorMatrixFilter 使った泥臭いやり方をしてる。
                 *      絶対にもっと良い方法があるハズ。って思いながら、
                 *      現状コレしか思い付かなかった :-(
                 *      ご存知の方が居られましたら教えておくんなまし!!
                 */
                cmf = new ColorMatrixFilter([
                    r/0xff, 0, 0, 0, 0,
                    0, g/0xff, 0, 0, 0,
                    0, 0, b/0xff, 0, 0,
                    0, 0, 0, 1, 0, 0,
                ]);

                //  元となる画像データを複製して
                bmd = seedBmd.clone();
                //  適当に作った色を適応させる
                bmd.applyFilter(bmd, bmd.rect, zp, cmf);

                //  それぞれを合わせて明るい色を作る
                hc = r << 16|g << 8|b;
                //  減色して暗い色を作る
                //dc = (r * .6) << 16|(g * .6) << 8|(b * .6);

                //  ボールを作って
                //material = new FlatShadeMaterial(light, hc, dc);
                material = new BitmapMaterial(bmd);
                sphere = new Sphere(material, 80, 12, 9);

                //  適当な位置を決めて
                sphere.x = Math.random() * 1500 - 750;
                sphere.y = Math.random() * 1500 - 750;
                sphere.z = Math.random() * 1500 - 750;

                //  コレやっとかないとフィルターが適応されない
                sphere.useOwnContainer = true;
                //  フィルターの設定
                sphere.filters = [
                    new GlowFilter(hc, .5, 32, 32, 2, BitmapFilterQuality.LOW),
                ];
                //  配置する
                root3d.addChild(sphere, 'sphere'+String(l));
            }

            //  イベントの設定
            addEventListener(Event.ENTER_FRAME, step);
        }

        /**
         *  毎フレーム呼ばれる処理
         */
        private function step(evt:Event):void
        {
            var l:uint,
                o:DisplayObject3D;

            //  指定個分だけ回す
            l = NUM_SPHERES;
            while (l--)
            {
                o = root3d.getChildByName('sphere'+String(l));
                //  取れなければスルー
                if (!o) continue;
                //  自転させる
                o.rotationY = (o.rotationY - 2) % 360;
            }

            //  Y 軸を軸として回す
            //  公転させる
            root3d.yaw(-1);

            //  ココで書き出し
            //  scene を camera で viewport なフィルムに撮る。そんな感じ
            renderer.renderScene(scene, camera, viewport);
        }

        /**
         *  Papervision3D の初期化。 BasicView はココをやってくれてる
         */
        private function setupPV3D():void
        {
            //  Camera3D
            //  デフォルトの位置は x=0 y=0 z=-1000
            camera = new Camera3D();

            //  PointLight3D
            //  デフォルトの位置は x=0 y=0 z=-1000
            light = new PointLight3D();
            //  上に移動
            light.y = 1000;

            //  BasicRenderEngine
            renderer = new BasicRenderEngine();

            //  Scene3D
            scene = new Scene3D();

            //  Viewport3D
            //  x=465 y=465 resizable=true に設定
            viewport = new Viewport3D(465, 465, true);
            addChild(viewport);
        }
    }
}