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

Astro Cube

Astro Cube
* 
* I've refered to the following posts
* てっく煮ブログ
* 
* AS3.0 で 3D プログラミングを1から勉強する (1)~(4)
* http://d.hatena.ne.jp/nitoyon/20080616/as_3d_lessen1
* http://d.hatena.ne.jp/nitoyon/20080617/as_3d_lessen2
* http://d.hatena.ne.jp/nitoyon/20080618/as_3d_lessen3
* http://d.hatena.ne.jp/nitoyon/20080620/as_3d_lessen3
* 
* Adobe デベロッパーセンター
* 
* Matrixクラス - 変換行列 
* http://www.adobe.com/jp/devnet/flash/articles/matrix_class.html
* 
* Matrix3Dクラス - 変換行列2 
* http://www.adobe.com/jp/devnet/flash/articles/matrix3d_class.html
* 
* fumioNonaka.com
* 
* Adobe Flash非公式テクニカルノート - 変換行列を数学的に捉える
* http://www.fumiononaka.com/TechNotes/Flash/FN0811001.html
*
*
Get Adobe Flash player
by yeq 26 Dec 2008
/*
 * Astro Cube
 * 
 * I've refered to the following posts
 * てっく煮ブログ
 * 
 * AS3.0 で 3D プログラミングを1から勉強する (1)~(4)
 * http://d.hatena.ne.jp/nitoyon/20080616/as_3d_lessen1
 * http://d.hatena.ne.jp/nitoyon/20080617/as_3d_lessen2
 * http://d.hatena.ne.jp/nitoyon/20080618/as_3d_lessen3
 * http://d.hatena.ne.jp/nitoyon/20080620/as_3d_lessen3
 * 
 * Adobe デベロッパーセンター
 * 
 * Matrixクラス - 変換行列 
 * http://www.adobe.com/jp/devnet/flash/articles/matrix_class.html
 * 
 * Matrix3Dクラス - 変換行列2 
 * http://www.adobe.com/jp/devnet/flash/articles/matrix3d_class.html
 * 
 * fumioNonaka.com
 * 
 * Adobe Flash非公式テクニカルノート - 変換行列を数学的に捉える
 * http://www.fumiononaka.com/TechNotes/Flash/FN0811001.html
 *
 *
 */
package {
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.geom.Vector3D;
	import flash.geom.Matrix3D;
	import flash.display.Graphics;
	import __AS3__.vec.Vector;
	import flash.geom.PerspectiveProjection;
	import flash.utils.Dictionary;
	
	[SWF(backgroundColor="#FFFFFF", frameRate="30")]
	public class Astro extends Sprite
	{
		public static var fov:PerspectiveProjection= new PerspectiveProjection();
        private var canvas:Sprite;
		private var rad:int;
		private var cube:Cube;
		
		public function Astro()
		{
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            
			cube = new Cube(0, 0, 0, 200)
            
           	canvas = new Sprite();
            addChild(canvas);
            canvas.x = 200;
            canvas.y = 200;
            canvas.z = 0;
            
            //視野角の設定
            fov.fieldOfView = 45;
            
            rad = 0;
            addEventListener(Event.ENTER_FRAME, function(evt:Event):void{render();});
		}
		private function render():void
		{
			canvas.graphics.clear();
			
            // 回転行列を作成
            var matrix:Matrix3D= new Matrix3D();
            
            //X軸方向に傾ける
            matrix.appendRotation(Math.PI/180*rad/2, Vector3D.X_AXIS);
            
            //Y軸方向に傾ける
            matrix.appendRotation(Math.PI/180*rad*3, Vector3D.Y_AXIS);           
            
            //Z軸方向に傾ける
            matrix.appendRotation(Math.PI/180*rad, Vector3D.Z_AXIS);          
                        
            cube.draw(canvas.graphics, matrix);
            
            // 角度更新
            rad += 10;
 		}
	}
}
	import flash.geom.Vector3D;
	import flash.geom.Matrix3D;
	import flash.display.Graphics;
	import __AS3__.vec.Vector;
	import flash.geom.PerspectiveProjection;
	import flash.utils.Dictionary;
	
class Cube 
{
    private var points:Vector.<Vector3D> = new Vector.<Vector3D>();

    public function Cube(x:Number, y:Number, z:Number, len:Number)
    {
        var diff:Function = function(f:Boolean):Number{return f ? len / 2 : -len / 2;};

        // 立方体の頂点8つを作成する
        for(var i:int = 0; i < 8; i++)
        {
            var p:Vector3D= new Vector3D(x + diff(i % 4 % 3 == 0),  y + diff(i % 4 < 2), z + diff(i < 4));
            points.push(p);
        }
    }
    public function draw(g:Graphics, matrix:Matrix3D):void 
    {
        // 回転後の各頂点の座標を計算
        var p:Vector.<Vector3D> = new Vector.<Vector3D>();
        
        for(var i:int = 0; i < points.length; i++)
        {
            //matrix.appendTranslation(points[i].x, points[i].y, points[i].z);
            var pt:Vector3D= matrix.transformVector(points[i]);

            var fov:PerspectiveProjection = Astro.fov;
            
            // 点を透視投影する
			pt.w = fov.focalLength / (fov.focalLength + pt.z);
            pt.project();
			
            //drawPoint(g, pt);
            p.push(pt);
        }

        // 頂点の間を線で結ぶ
        for(i = 0; i < 4; i++)
        {
            //drawLine(g, p[i], p[i + 4]);
            //drawLine(g, p[i], p[(i + 1) % 4]);
            //drawLine(g, p[i + 4], p[(i + 1) % 4 + 4]);
        }
        
        // 面の一覧
        var planes:Array = [
            [p[0], p[1], p[2], p[3]],
            [p[7], p[6], p[5], p[4]],
            [p[0], p[4], p[5], p[1]],
            [p[1], p[5], p[6], p[2]],
            [p[2], p[6], p[7], p[3]],
            [p[3], p[7], p[4], p[0]]
        ];
        
        // 面の中心のZ座標を求める
        var z:Dictionary= new Dictionary();
        for(i = 0; i < planes.length; i++)
        {
            z[planes[i]] = (planes[i][0].z + planes[i][1].z + planes[i][2].z + planes[i][3].z) / 4;
        }

        // Zソート (奥のものから順番に並べる)
        planes.sort(function(a:Array, b:Array):Number 
        {
            return z[b] - z[a];
        });

        // 奥から順番に面を描画
        var counter:int = 0;
        for each(var plane:Array in planes)
        {
            drawPlane(g, plane[0], plane[1], plane[2], plane[3]);            
        }
    }
    private function drawPlane(g:Graphics, p1:Vector3D, p2:Vector3D, p3:Vector3D, p4:Vector3D):void 
    {
        // 単位法線ベクトル
        var v1:Vector3D = p2.subtract(p1);
        var v2:Vector3D = p4.subtract(p1);
        
        // ベクトルの外積(2つのベクトルに垂直なベクトル)
        var n:Vector3D= cross(v1, v2);
        //単位ベクトル(長さ1のベクトル)に変換
        n.normalize();

        // 光源の方向ベクトルとの内積
        var l:Vector3D = new Vector3D(0, 0, -1);
        //l と n の内積を面の明るさとする(ランバートの法則)
        var brightness:Number = dot(n, l);

        // 面を塗る
        var b:int = 0x3f * brightness + 0xc0;
        g.beginFill(b * 0x10000 + b * 0x100 + b, 0.2);
        
        g.lineStyle(0, 0x666666);
        var p:Vector3D;
        p = p1.clone(); g.moveTo(p.x, p.y);
        p = p2.clone(); g.lineTo(p.x, p.y);
        p = p3.clone(); g.lineTo(p.x, p.y);
        p = p4.clone(); g.lineTo(p.x, p.y);
        g.endFill();
    }
    private function drawPoint(g:Graphics, p:Vector3D):void 
    {
        g.beginFill(0x000000);
        g.drawCircle(p.x, p.y, 3);
        g.endFill();
    }
    private function drawLine(g:Graphics, p1:Vector3D, p2:Vector3D):void 
    {
        g.beginFill(0, 0);
        g.lineStyle(1, 0x000000);
        g.moveTo(p1.x, p1.y);
        g.lineTo(p2.x, p2.y);
        g.lineStyle();
        g.endFill();
    }
	// 外積
	private function cross(p1:Vector3D, p2:Vector3D):Vector3D 
	{
	    return new Vector3D(p1.y * p2.z - p1.z * p2.y,
	                       p1.z * p2.x - p1.x * p2.z,
	                       p1.x * p2.y - p1.y * p2.x);
	}
	// 内積
	private function dot(p1:Vector3D, p2:Vector3D):Number 
	{
		return p1.x * p2.x + p1.y * p2.y + p1.z * p2.z;
	}
}