In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

transformVectors+BitmapDataで3D表示にエフェクト追加

/**
 * Copyright nitoyon ( http://wonderfl.net/user/nitoyon )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/3S7x
 */

// forked from nitoyon's transformVectors+BitmapDataで3D表示
// forked from nitoyon's transformVectorsで透視投影して3D表示
// forked from nitoyon's Utils3D.projectVectorsの練習
package{
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;

[SWF(width=450,height=450,backgroundColor=0x000000, frameRate=12)]
public class TestTriangles extends Sprite{
	private const N:int = 400;
	private const R:int = 250;
	private const CANVAS_SIZE:int = 450;
	private const COUNT:int = 40; // 表示するボール画像の数
	private const BALL_SIZE:int = 40; // 表示するボール画像の数

	public function TestTriangles(){
		stage.scaleMode = "noScale";
		stage.align = "TL";

		// 100個の点を3D座標空間に作成する
		var points:Vector.<Number> = new Vector.<Number>();
		for(var i:int = 0; i < N; i++){
			points.push(Math.random() * R * 2 - R); // X座標
			points.push(Math.random() * R * 2 - R); // Y座標
			points.push(Math.random() * R * 2 - R); // Z座標
		}

		// 変換行列
		var mtx:Matrix3D = new Matrix3D();

		// 変換結果の座標
		var results:Vector.<Number> = new Vector.<Number>();

		// コピーする画像を作成
		var balls:Vector.<BitmapData> = createBalls();

		// キャンバスを準備
		var canvas:BitmapData = new BitmapData(CANVAS_SIZE, CANVAS_SIZE);
		var bmp:Bitmap = addChild(new Bitmap(canvas)) as Bitmap;

		// インデックス一覧を作成
		var indices:Vector.<int> = new Vector.<int>(N);
		for(i = 0; i < N; i++){
			indices[i] = i;
		}

		// 毎フレーム処理
		var pt:Point = new Point();
		var ptZero:Point = new Point();
		var filter1:BitmapFilter = new ColorMatrixFilter([
			.9,  0,  0, 0, 0, 
			 0, .6,  0, 0, 0, 
			 0,  0, .4, 0, 0, 
			 0,  0,  0, 1, 0
		]);
		var filter2:BitmapFilter = new BlurFilter(4, 4);
		addEventListener("enterFrame", function(event:Event):void{
			// 変換行列の角度を増やす
			mtx.appendRotation(2, Vector3D.Y_AXIS);
			mtx.appendRotation(1.1, Vector3D.X_AXIS);
			mtx.appendRotation(.8, Vector3D.Z_AXIS);

			// 座標を回転させる
			mtx.transformVectors(points, results);

			// Zソートする
			indices = indices.sort(function(x:int, y:int):int{
				var z1:Number = results[x * 3 + 2];
				var z2:Number = results[y * 3 + 2];
				return z1 > z2 ? 1 : z1 < z2 ? -1 : 0;
			});

			// 描画する
			canvas.lock();
			for(var i:int = 0; i < N; i++){
				var ii:int = indices[i];

				// Z座標から表示する画像を決める
				var z:Number = results[ii * 3 + 2];
				var num:int = (z / (2 * R * Math.sqrt(2)) + 1) / 2 * COUNT;

				// 表示
				pt.x = results[ii * 3] + CANVAS_SIZE / 2;
				pt.y = results[ii * 3 + 1] + CANVAS_SIZE / 2;
				canvas.copyPixels(balls[num], balls[num].rect, pt, balls[num], null, true);
			}
			canvas.applyFilter(canvas, canvas.rect, ptZero, filter1);
			canvas.applyFilter(canvas, canvas.rect, ptZero, filter2);
			canvas.unlock();
		});
	}

	// ボールの画像一覧を生成する
	private function createBalls():Vector.<BitmapData>{
		var balls:Vector.<BitmapData> = new Vector.<BitmapData>();

		var s:Sprite = new Sprite();
		for(var i:int = 0; i < COUNT; i++){
			// パラメータの計算
			var ratio:Number = i / COUNT;
			var col:uint = Math.min(0xff * Math.abs(ratio * 2 - 1) + 0x80, 0xff);
			col = (col * 0x10000) + (col * 0x100) + col;
			var blur:Number = Math.abs(ratio - .5) * 30 + 5;

			// Sprite に描画
			s.graphics.clear();
			s.graphics.beginFill(col);
			s.graphics.drawCircle(BALL_SIZE / 2, BALL_SIZE / 2, BALL_SIZE * ratio / 2);
			s.graphics.drawCircle(BALL_SIZE / 2, BALL_SIZE / 2, BALL_SIZE * ratio / 16);
			s.graphics.endFill();
			s.filters = [new BlurFilter(blur, blur)];

			// Sprite を BitmapData に描画
			var bmd:BitmapData = new BitmapData(BALL_SIZE, BALL_SIZE, true, 0x0);
			bmd.draw(s);

			// balls に追加
			balls.push(bmd);
		}

		return balls;
	}
}
}