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