3D Balls
3Dの練習
画面をclickすると、描画方式が切り替わります
/**
* Copyright nackpan ( http://wonderfl.net/user/nackpan )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/eoZQ
*/
//3Dの練習
//画面をclickすると、描画方式が切り替わります
package {
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Matrix3D;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.geom.Vector3D;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.display.GradientType;
import flash.display.SpreadMethod;
[SWF(backgroundColor = 0xF0F0F0)]
public class FlashTest extends Sprite {
private var BALL_MAX:int = 600;
/////copyPixels描画関連
//copyPixelsの素材
private var pngBmp:Bitmap;
private var ballData:BitmapData;
//カンバスになるbitmap
private var canvasBmp:Bitmap;
private var canvasData:BitmapData;
private var baseData:BitmapData;
///copyPixelsを使用するために用意するもの
private var pngCopyData:BitmapData;
private var sourceRect:Rectangle;
private var destPoint:Point;
private var txt:TextField;
private var objs:Vector.<Ball3D>;
private var centerZ:Number = 200;
private var focalLength:Number = 400;// 250;
//
private var view_offset_x:int;
private var view_offset_y:int;
private var count:int = 0;
private var vin:Vector.<Number>;
private var vout:Vector.<Number>;
private var ballCopySource:Vector.<BitmapData>;
////描画モード
private var mode:int = 0;
public function FlashTest() {
// write as3 code here..
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
view_offset_x = stage.stageWidth / 2;
view_offset_y = stage.stageHeight / 2;
var i:int;
var j:int;
var s:int = 3200;
var v_range:int = 0;// 100;
vin = new Vector.<Number>(BALL_MAX * 3);
vout = new Vector.<Number>(BALL_MAX * 3);
objs = new Vector.<Ball3D>(BALL_MAX);
for (i = 0; i < BALL_MAX; i++)
{
var obj:Ball3D = new Ball3D();
obj.init(
Math.round(Math.random() * s - s / 2) ,
Math.round((Math.random() * s - s / 2) ),
Math.round(Math.random() * s - s / 2) ,
Math.round(Math.random() * v_range - v_range / 2) * 2,
Math.round((Math.random() * v_range - v_range / 2) / 2),
Math.round(Math.random() * v_range - v_range / 2),
i);
objs[i] = obj;
}
//ボール画像を用意
ballData = makeShape();
canvasData = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0x000000);
baseData = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0xF0F0F0);
//キャンバスを用意
canvasBmp = new Bitmap(canvasData);
this.addChild(canvasBmp);
canvasBmp.visible = false;
////copyPixelsを用いて描画するための準備//////
///////あらかじめ、各スケールのボールのbitmapDataを作成しておく(0-0.4まで、0.01刻み)
var m:Matrix = new Matrix();
ballCopySource = new Vector.<BitmapData>();
for (i = 0; i < 40; i++) {
var scale:Number = i * .01;
if (scale == 0) scale = .5;
var bmpData:BitmapData = new BitmapData(200 * scale, 200 * scale, true, 0);
m.a = i * .01;
m.d = i * .01;
bmpData.draw(ballData, m);
ballCopySource[i] = bmpData;
}
sourceRect = new Rectangle(0,0,60,60);
destPoint = new Point();
txt = new TextField();
txt.width = 160;
txt.height = 20;
txt.border = true;
txt.background = true;
txt.backgroundColor = 0xffffee;
addChild(txt);
txt.text = "graphic.drawCircle";
stage.addEventListener(MouseEvent.MOUSE_DOWN, mousedown);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function mousedown(event:MouseEvent):void
{
mode += 1;
if (mode > 2) mode = 0;
if (mode == 0) {
txt.text = "graphic.drawCircle"; canvasBmp.visible = false;
}
if (mode == 1) {
txt.text = "bitmapData.draw"; canvasBmp.visible = true;
}
if (mode == 2) {
txt.text = "bitmapData.copyPixels"; canvasBmp.visible = true;
}
}
private function makeShape():BitmapData
{
var shape:Shape = new Shape();
//gradient
var fillType:String = GradientType.RADIAL;
var colors:Array = [0xFFFFFF, 0xFFFEFD, 0xFF4444, 0xFE4444, 0xFD4444];
//var colors:Array = [0xFFFFFF, 0xFFFEFD, 0xBAAAAA, 0xB99999, 0xB88888];
var alphas:Array = [1, 1, 1, 1, 1];
var ratios:Array = [0x00, 0x02, 0xE0, 0xFA, 0xFF];
var matr:Matrix = new Matrix();
matr.createGradientBox(200, 200, 0, 0, -70);
var spreadMethod:String = SpreadMethod.REFLECT;
shape.graphics.beginGradientFill(fillType, colors, alphas, ratios, matr, spreadMethod, "rgb", 0);// .5);
shape.graphics.drawCircle(100, 100, 100 );
var bmpData:BitmapData = new BitmapData(200, 200, true, 0);
bmpData.draw(shape, new Matrix(), null, null, null, true);
return bmpData;
}
private function sortShapes():void
{
objs.sort(depthSort);
}
private function depthSort(objA:Ball3D, objB:Ball3D):int
{
var posA:Vector3D = objA.viewPos;
var posB:Vector3D = objB.viewPos;
return posB.z - posA.z;
}
private function onEnterFrame(event:Event):void
{
if (mode == 0) {
draw1();
}
if (mode == 1) {
draw2();
}
if (mode == 2) {
draw3();
}
}
//drawCircleで描いてみる
private function draw1():void
{
count++;
//ビュー変換用のMatrix3D
var m3D:Matrix3D = new Matrix3D();
//カメラの回転を戻す
m3D.appendRotation(-count * 2 , Vector3D.Y_AXIS);
m3D.prependRotation( -60, Vector3D.X_AXIS);
//カメラの移動を戻す
m3D.appendTranslation(0, 0, 3000 );
var m:Matrix = new Matrix();
var i:int;
var s:int = 0;
for (i = 0; i < BALL_MAX; i++) {
//ワールド座標
vin[s++] = objs[i].pos.x;
vin[s++] = objs[i].pos.y;
vin[s++] = objs[i].pos.z;
}
//ビュー変換
/////////transformVectors使用
m3D.transformVectors(vin, vout);
s = 0;
for (i = 0; i < BALL_MAX; i++) {
objs[i].viewPos.x = vout[s++];
objs[i].viewPos.y = vout[s++];
objs[i].viewPos.z = vout[s++];
}
//zソート
sortShapes();
//描画
graphics.clear();
graphics.lineStyle(0);
for (i = 0; i < BALL_MAX; i++){
var scale:Number = focalLength / (focalLength + objs[i].viewPos.z + centerZ);
graphics.beginFill(0xffffff);
graphics.drawCircle(( objs[i].viewPos.x + 100) * scale + view_offset_x,
( objs[i].viewPos.y + 100) * scale + view_offset_y,
100 * scale);
graphics.endFill();
}
}
//bitmapData.drawで描いてみる
private function draw2():void
{
count++;
//ビュー変換用のMatrix3D
var m3D:Matrix3D = new Matrix3D();
//カメラの回転を戻す
m3D.appendRotation(-count * 2 , Vector3D.Y_AXIS);
m3D.prependRotation( -60, Vector3D.X_AXIS);
//カメラの移動を戻す
m3D.appendTranslation(0, 0, 3000 );
var m:Matrix = new Matrix();
var i:int;
canvasData.lock();
canvasData.draw(baseData);
var s:int = 0;
for (i = 0; i < BALL_MAX; i++) {
//ワールド座標
vin[s++] = objs[i].pos.x;
vin[s++] = objs[i].pos.y;
vin[s++] = objs[i].pos.z;
}
//ビュー変換
/////////transformVectors使用
m3D.transformVectors(vin, vout);
s = 0;
for (i = 0; i < BALL_MAX; i++) {
objs[i].viewPos.x = vout[s++];
objs[i].viewPos.y = vout[s++];
objs[i].viewPos.z = vout[s++];
}
//zソート
sortShapes();
//描画
for (i = 0; i < BALL_MAX; i++){
var scale:Number = focalLength / (focalLength + objs[i].viewPos.z + centerZ);
//カメラ座標
m.tx = objs[i].viewPos.x * scale + view_offset_x;
m.ty = objs[i].viewPos.y * scale + view_offset_y;
m.a = scale;
m.d = scale;
canvasData.draw(ballData, m);
}
canvasData.unlock();
}
//bitmapData.copyPixelsで描いてみる
private function draw3():void
{
count++;
//ビュー変換用のMatrix3D
var m3D:Matrix3D = new Matrix3D();
//カメラの回転を戻す
m3D.appendRotation(-count * 2, Vector3D.Y_AXIS);
m3D.prependRotation( -60, Vector3D.X_AXIS);
//カメラの移動を戻す
m3D.appendTranslation(0, 0, 3000 );
var i:int;
canvasData.lock();
canvasData.draw(baseData);
var s:int = 0;
for (i = 0; i < BALL_MAX; i++) {
//ワールド座標
vin[s++] = objs[i].pos.x;
vin[s++] = objs[i].pos.y;
vin[s++] = objs[i].pos.z;
}
//ビュー変換
/////////transformVectors使用
m3D.transformVectors(vin, vout);
s = 0;
for (i = 0; i < BALL_MAX; i++) {
objs[i].viewPos.x = vout[s++];
objs[i].viewPos.y = vout[s++];
objs[i].viewPos.z = vout[s++];
}
//zソート
sortShapes();
//描画
for (i = 0; i < BALL_MAX; i++){
var scale:Number = focalLength / (focalLength + objs[i].viewPos.z + centerZ);
destPoint.x = objs[i].viewPos.x * scale + view_offset_x;
destPoint.y = objs[i].viewPos.y * scale + view_offset_y;
var n:int = int(scale * 100);
if (n >= 40) n = 39;
sourceRect.width = ballCopySource[n].width;
sourceRect.height = ballCopySource[n].height;
canvasData.copyPixels(ballCopySource[n], sourceRect, destPoint);
}
canvasData.unlock();
}
}
}
import flash.geom.Vector3D;
class Ball3D
{
public var pos:Vector3D;
public var viewPos:Vector3D;
public var v:Vector3D;
public var n:int;
public function Ball3D():void
{
}
public function init(x:Number, y:Number, z:Number,
vx:Number, vy:Number, vz:Number,
n:int):void
{
pos = new Vector3D(x, y, z, 0);
v = new Vector3D(vx, vy, vz, 0);
//this.sp = sp;
this.n = n;
viewPos = new Vector3D();
}
}