Beautifl - Flash Gallery

Thumbnail : forked from: レインボーロード!  forked from: nengafl
forked from: レインボーロード! forked from: nengafl
uwi 2010-01-22 MIT License

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

// 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);
    }
}