Beautifl - Flash Gallery

Preview

forked from: レインボーロード! forked from: nengafl
uwi 2010年1月22日 MIT License
?
PV3Dで簡単に綺麗な図形を作ってみよう!  
  
PV3Dを使うと3Dを超簡単に扱えます。  
そこで、PV3Dで簡単に綺麗な図形を作ってみましょう。  
簡単な数式とパラメータだけで綺麗な図形が完成!  
下で定義してある定数のp, q, a, l, m をいじってみてください。  
  
また、for文の中の数式を書き換えるとさらに形が変わります。  
単純に、sin → cos みたいに書き換えてみてもおもしろいかも!
      // forked from sake's レインボーロード!  forked from: nengafl
// forked from nengafl's nengafl
/*
   PV3Dで簡単に綺麗な図形を作ってみよう!

   PV3Dを使うと3Dを超簡単に扱えます。
   そこで、PV3Dで簡単に綺麗な図形を作ってみましょう。
   簡単な数式とパラメータだけで綺麗な図形が完成!
   下で定義してある定数のp, q, a, l, m をいじってみてください。
   
   また、for文の中の数式を書き換えるとさらに形が変わります。
   単純に、sin → cos みたいに書き換えてみてもおもしろいかも!
*/
 
 
package
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.BlendMode;
    import flash.events.Event;
    import flash.geom.Matrix;
    import frocessing.color.*;
    import org.papervision3d.core.geom.Pixels;
    import org.papervision3d.core.geom.renderables.Pixel3D;
    import org.papervision3d.view.BasicView;
    import org.papervision3d.view.layer.BitmapEffectLayer;
        import org.papervision3d.objects.*;
        import org.papervision3d.core.math.*;

    [SWF(width="465", height="465", backgroundColor="0x000000", frameRate="30")]
    public class Nengafl extends BasicView
    {
        // 計算に使うパラメータ
        // このあたりを適当に変えてみるだけでも面白いです!
        //----------------------------------------------------------------
        private const p:int=3;
        private const q:int=7;
        private const a:int=100;
        private const l:Number=0.9;
        private const m:Number=1.1;
        //----------------------------------------------------------------

        private var pixels:Pixels;
        private var canvas:BitmapData;
        private var mtx:Matrix;

        // コンストラクタ
        public function Nengafl()
        {
            super(0, 0, true, false);
            graphics.beginFill(0x000000);
            graphics.drawRect(0, 0, 465, 465);
            graphics.endFill();
            
            // レイヤー作成。PV3Dでエフェクト使うときはこれを最初に作ります
            var layer:BitmapEffectLayer=new BitmapEffectLayer(viewport, 465, 465, true, 0, "clear_pre", true);
            layer.clearBeforeRender=true;
            viewport.containerSprite.addLayer(layer);

//            camera.z=-500;

            // Pixelsの初期化
            pixels=new Pixels(layer);
            scene.addChild(pixels);

            var cc:ColorHSV=new ColorHSV();

            // パラメータと数式でPixelの位置を計算する
                        for(var i : Number = 0;i < 720;i+=0.2){
                            var t : Number = i * Math.PI / 120;
                // 数式に従ってx, y, z を計算。ここを適当に変えてみても面白いです。
                // 簡単にsin → cos に変えてみるとか!
                var xx:Number=(2 + Math.cos(q / p * t)) * Math.cos(t) * a;
                var yy:Number=Math.sin(q / p * t) * a * 1.6;
                var zz:Number=(2 + Math.cos(q / p * t)) * Math.sin(t) * a;

                // 綺麗なグラデーションになるように色を設定
                // こういうときはHSVを使うのが便利です
                cc.hsv(i, 1, 1);
                var color:uint=cc.value32;

                for (var j:int=0; j < 15; j++)
                {
                    // x, y, z を l~mの範囲で散らします。
                    // l~mの区間の乱数を出す計算:(m - l) * Math.random() + l
                    var px:Pixel3D=new Pixel3D(color, xx * ((m - l) * Math.random() + l), yy * ((m - l) * Math.random() + l), zz * ((m - l) * Math.random() + l));
                    pixels.addPixel3D(px);
                }
            }

            // キラキラロジック
            canvas=new BitmapData(465 / 4, 465 / 4, false, 0x000000);
            var bmp:Bitmap=new Bitmap(canvas, "never", true);
            bmp.scaleX=bmp.scaleY=4;
            bmp.smoothing=true;
            bmp.blendMode=BlendMode.ADD;
            addChild(bmp);
            mtx=new Matrix(0.25, 0, 0, 0.25);

            // PV3Dの描写開始!
            startRendering();

                        _rider = new DisplayObject3D();
                _rider.x =(2 + Math.cos(q / p * _t)) * Math.cos(_t) * a;
                _rider.y =Math.sin(q / p * _t) * a * 1.6;
                _rider.z =(2 + Math.cos(q / p * _t)) * Math.sin(_t) * a;
                        _camera = new RidingCamera(_rider, new Number3D(0, 1, 0), null);
        }

                private var _t : Number = 0.0;
                private var _rider : DisplayObject3D;

        // フレームイベント用関数
                override protected function onRenderTick(e : Event = null) : void
                {
                    // キラキラを描写
            canvas.fillRect(canvas.rect, 0x000000);
            canvas.draw(viewport, mtx);

            // Y軸でローテーション
//            pixels.rotationY+=0.2;

                        _t += 0.01;
                var xx:Number=(2 + Math.cos(q / p * _t)) * Math.cos(_t) * a;
                var yy:Number=Math.sin(q / p * _t) * a * 1.6;
                var zz:Number=(2 + Math.cos(q / p * _t)) * Math.sin(_t) * a;
                        _rider.x = xx;
                        _rider.y = yy;
                        _rider.z = zz;
                        RidingCamera(_camera).move(0, 0);

                        super.onRenderTick(e);
        }
        }
}

import org.papervision3d.core.math.*;
import org.papervision3d.objects.*;
import org.papervision3d.cameras.*;
// ジンバルロックを解消した以外はCamera3Dと同じ
class QCamera3D extends Camera3D
{
    public var _up : Number3D; // カメラの上の向きの単位ベクトル
    protected var _front : Number3D;
    private var _prevDir : Number3D;
    private var _ltarg : DisplayObject3D;
    
    public function QCamera3D(up : Number3D, front : Number3D = null)
    {
        super();
        _up = null;
        _ltarg = new DisplayObject3D();
        init(up, front);
    }
    
    // prevDirからcurDirへ向ける回転を_upにかけるだけ。カメラ自体に操作はしない
    public function rotate(curDir : Number3D) : void
    {
        if(_prevDir != null){
            var n : Number3D = Number3D.cross(_prevDir, curDir);
//            if(n.moduloSquared > 0.00000001){
            if(n.moduloSquared != 0){
                n.normalize();
                var angle : Number = Math.acos(Number3D.dot(_prevDir, curDir));
                if(_front != null){
                    var a : Array = applyQuaternion([_front, _up], n, angle);
                    _front = a[0];
                    _up = a[1];
                }else{
                    _up = applyQuaternion([_up], n, angle)[0];
                }
            }
            _prevDir.copyFrom(curDir);
        }else{
            _prevDir = curDir.clone();
        }
    }
    
    // カメラの右方向へx[rad], 上方向へy[rad]回転させる
    public function rotateXY(x : Number, y : Number) : void
    {
        if(_front == null)return;
        
        // X方向の移動
        _front = applyQuaternion([_front], _up, -x)[0];
        
        // Y方向の移動
        var right : Number3D = Number3D.cross(_up, _front);
        right.normalize();
        var ret : Array = applyQuaternion([_front, _up], right, y);
        _front = ret[0];
        _up = ret[1];
    }
    
    public function head() : void
    {
        if(_front != null){
            // まわりくどい
            var ltpos : Number3D = this.position.clone();
            ltpos.plusEq(_front);
            _ltarg.position = ltpos;
            this.lookAt(_ltarg, _up);
        }
    }
    
    public function init(up : Number3D = null, front : Number3D = null) : void
    {
        if(up != null){
            _up = up.clone();
            _up.normalize();
        }
        if(front != null){
            _front = front.clone();
            _front.normalize();
        }else{
            _front = null;
        }
        _prevDir = null;
    }
    
    // axisを軸にangle回転させる変換を、srcsの要素それぞれに適用する
    public static function applyQuaternion(srcs : Array, axis : Number3D, angle : Number) : Array
    {
        var q : Quaternion = Quaternion.createFromAxisAngle(
            axis.x / axis.modulo, 
            axis.y / axis.modulo, 
            axis.z / axis.modulo,
            angle
            );
        var qc : Quaternion = Quaternion.conjugate(q);
        
        var ret : Array = [];
        for each(var src : Number3D in srcs){
            var qSrc : Quaternion = new Quaternion(src.x, src.y, src.z, 0);
            var qDst : Quaternion = Quaternion.multiply(qc, qSrc);
            qDst.mult(q);
            ret.push(new Number3D(qDst.x, qDst.y, qDst.z));
        }
        return ret;
    }
    
}

// ゲットライド!
class RidingCamera extends QCamera3D
{
    private var _ride : DisplayObject3D;
    private var _prevPos : Number3D;
    
    public function RidingCamera(ride : DisplayObject3D, up : Number3D, front : Number3D = null)
    {
        super(up, front);
        _ride = ride;
        _prevPos = _ride.position.clone();
    }
    
    public function move(up : Number = 0, back : Number = 0) : void
    {
        var curDir : Number3D = Number3D.sub(_ride.position, _prevPos);
        curDir.normalize();
        if(_front == null){
            _front = curDir.clone();
        }
        rotate(curDir);
        
        var curPos : Number3D = _ride.position.clone();
        var temp : Number3D;
        temp = _up.clone();
        temp.multiplyEq(up);
        curPos.plusEq(temp);
        temp = _front.clone();
        temp.multiplyEq(-back);
        curPos.plusEq(temp);
        this.position = curPos;
        
        head();
        _prevPos.copyFrom(_ride.position);
    }
}