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

My 3D Engine

---------------------------------------------------------------------
5〜6年前にAS2で書いた3D描画ライブラリを発掘したのでAS3用に修正して晒してみるテスト
---------------------------------------------------------------------
Get Adobe Flash player
by hycro 14 Feb 2016
    Embed
/**
 * Copyright hycro ( http://wonderfl.net/user/hycro )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/66rS
 */

// ---------------------------------------------------------------------
//  5〜6年前にAS2で書いた3D描画ライブラリを発掘したのでAS3用に修正して晒してみるテスト
// ---------------------------------------------------------------------
package
{
    import flash.display.Shape;
    import flash.display.Sprite;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    
    import net.hires.debug.Stats;

    public class My3DEngineTest extends Sprite
    {
        private const CUBE_NUM:uint = 300;
        private var _scr:Screen;
        private var _canvas:Shape;
        private var _cubes:Vector.<Cube>
        
        public function My3DEngineTest()
        {
            stage.frameRate = 60;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            
            // 座標変換や描画を行うScreenのインスタンスを作成
            _scr = new Screen();
            // カメラの焦点距離を設定
            _scr.setFocusValue(300);
            // 注視点の設定
            _scr.setLookingpoint(0, 0, 0);
            
            // 描画用
            _canvas = new Shape();
            _canvas.x = stage.stageWidth / 2;
            _canvas.y = stage.stageHeight / 2;
            addChild(_canvas);
            
            // 立方体モデルを作成
            _cubes = new Vector.<Cube>();
            for (var i:uint=0; i<CUBE_NUM; i++) {
                var cube:Cube = new Cube(Model.POLYGON, 20);
                cube.setPolygonColor(Math.random() * 0xffffff);
                cube.translate((Math.random()-.5)*300, (Math.random()-.5)*300, (Math.random()-.5)*300);
                _scr.addModel(cube);
                _cubes.push(cube);
            }
            // 球体モデルを作成
            //var sphere:Sphere = new Sphere(30, 10, 10);
            //_scr.addModel(sphere);
            
            addEventListener(Event.ENTER_FRAME, onEnterFrame);
            addChild(new Stats);
        }
        
        private var t:Number = 0;
        private function onEnterFrame(evt:Event):void {
            t += .01
                
            // カメラの位置
            _scr.setViewpoint(350*Math.cos(t), 350*Math.sin(t), 350*Math.sin(t));
            
            // 光源の位置(平行光線の方向ベクトル)を設定
            _scr.setLight(300*Math.cos(t), 300, 300*Math.sin(t));
            
            _canvas.graphics.clear();
            
            for each (var cube:Cube in _cubes) {
                // 原点を中心に回転
                cube.rotate(1, 1, 1);
                // 移動
                //cube.translate((Math.random()-.5)*10,(Math.random()-.5)*10,(Math.random()-.5)*10);
                // 拡大縮小
                //cube.scale(1+(Math.random()-.5)*.01,1+(Math.random()-.5)*.01,1+(Math.random()-.5)*.01);
            }
            
            // 透視投影でポリゴンを描画
            _scr.drawPerspectivePolygon(_canvas.graphics);
            
            // 投資投影でワイアーフレームを描画
            //_scr.drawPerspectiveWire(_canvas.graphics);
            
            // 平行投影でポリゴンを描画
            //_scr.draw(_canvas.graphics);
        }
    }
}

//package simple3d {
    import flash.display.*;
    
    /*public*/ class Screen {
        private var nViewpointX:Number, nViewpointY:Number, nViewpointZ:Number;           // 視点
        private var nLookingpointX:Number, nLookingpointY:Number, nLookingpointZ:Number;  // 注視点
        private var arModels:Array;                                         // 配置するモデル
        private var mLight:Light;                                             // 拡散反射平行光線
        private var nFocus:Number;                                            // 焦点距離
        
        // コンストラクタ
        function Screen() {
            setViewpoint(0, 0, 100);
            setLookingpoint(0, 0, 0);
            setFocusValue(200);
            arModels = new Array();
            mLight = new Light(1, 1 , 1);
        }
        
        // モデルを追加
        public function addModel(model:Model):void {
            arModels.push(model);
        }
        
        // 焦点距離を設定
        public function setFocusValue( n:Number ):void {
            nFocus = n;
        }
        
        // 視点座標を設定
        public function setViewpoint( x:Number, y:Number, z:Number ):void {
            nViewpointX = x;
            nViewpointY = y;
            nViewpointZ = z;
        }
        
        // 注視点座標を設定
        public function setLookingpoint( x:Number, y:Number, z:Number ):void {
            nLookingpointX = x;
            nLookingpointY = y;
            nLookingpointZ = z;
        }
        
        // 光源方向を設定
        public function setLight( x:Number, y:Number, z:Number ):void {
            mLight.arVertex[1][0] = x;
            mLight.arVertex[1][1] = y;
            mLight.arVertex[1][2] = z;
        }
        
        //透視投影でのワイヤーフレーム表示
        public function drawPerspectiveWire(m:Graphics):void {
            var nScrX:Number, nScrY:Number;
            var i:int, j:int, k:int;
            var mCurr:Model;                          // 現在描写しているモデル
            var arViewVertex:Array;                      // 視点座標系での頂点の座標値
            var arScrVertex:Array = new Array();       // スクリーン座標系での頂点の座標値
            
            for (i=0; i<arModels.length; i++) {
                mCurr = arModels[i];
                
                // 視野変換
                arViewVertex = viewingTransform(mCurr);
                            
                // 投影変換
                for (j=0; j<mCurr.arVertex.length; j++) {
                    nScrX = nFocus*arViewVertex[j][0] / ( nFocus + arViewVertex[j][2]  );
                    nScrY = nFocus*arViewVertex[j][1] / ( nFocus + arViewVertex[j][2]  );
                    arScrVertex[j] = [nScrX, nScrY];
                }
                
                // 描画
                m.lineStyle( mCurr.nEdgeSize, mCurr.nEdgeColor );
                for ( j=0; j<mCurr.arEdge.length; j++ ) {
                    m.moveTo(arScrVertex[mCurr.arEdge[j][0]][0], -arScrVertex[mCurr.arEdge[j][0]][1]);
                    for (k=1; k<mCurr.arEdge[j].length; k++)
                        m.lineTo(arScrVertex[mCurr.arEdge[j][k]][0], -arScrVertex[mCurr.arEdge[j][k]][1]);
                }
            }
        }
        
        //透視投影でのポリゴン表示
        public function drawPerspectivePolygon(m:Graphics):void {
            var i:int, j:int, k:int;
            var mCurr:Model;                              // 現在描写しているモデル
            var arScrVertex:Array = new Array();       // スクリーン座標系での頂点の座標値
            var nScrX:Number, nScrY:Number;
            var arNormal:Array;
            var nInnerProduct:Number;
            var nViewVectX:Number, nViewVectY:Number, nViewVectZ:Number;  // 視点から頂点へのベクトル
            var nTotalZ:Number;
            var nLightX:Number, nLightY:Number, nLightZ:Number, nLightLength:Number; // 光線の方向ベクトル
            var nRef:Number;
            var nCos:Number;
            var nColor:Number, nR:Number, nG:Number, nB:Number;
            
            var arViewVertex:Array, arPolygon:Array;
            
            // カメラ座標系における光線の方向ベクトルを求める
            mLight.arViewVertex =  viewingTransform(mLight); 
            nLightX = mLight.arViewVertex[0][0] - mLight.arViewVertex[1][0];
            nLightY = mLight.arViewVertex[0][1] - mLight.arViewVertex[1][1];
            nLightZ = mLight.arViewVertex[0][2] - mLight.arViewVertex[1][2];
            nLightLength = Math.sqrt( nLightX*nLightX + nLightY*nLightY + nLightZ*nLightZ );
            
            // 視野変換を行い、奥にあるものから順に並ぶようにモデルをソートする 
            for ( i=0; i<arModels.length; i++ ) {
                mCurr =  arModels[i];
                // 視野変換
                mCurr.arViewVertex = viewingTransform(mCurr);
                // 重心の z 座標を計算
                nTotalZ = 0;
                for ( j=0; j<mCurr.arViewVertex.length; j++ ) 
                    nTotalZ += mCurr.arViewVertex[j][2];
                mCurr.nCenterZ = nTotalZ / mCurr.arViewVertex.length;
            }
            arModels.sortOn("nCenterZ", Array.NUMERIC );
            
            for (i=arModels.length-1; i>=0; i--) {
                mCurr = arModels[i];
                arViewVertex = mCurr.arViewVertex;
                arPolygon = mCurr.arPolygon;
                
                // 投影変換
                for (j=0; j<mCurr.arVertex.length; j++) {
                    nScrX = nFocus*arViewVertex[j][0] / (  arViewVertex[j][2]  );
                    nScrY = nFocus*arViewVertex[j][1] / (  arViewVertex[j][2]  );
                    arScrVertex[j] = [nScrX, nScrY];
                }
                
                // 各ポリゴンの法線ベクトルを求める
                arNormal = calcNormal(mCurr);
                    
                for ( j=0; j<mCurr.arPolygon.length; j++ ) {
                    // 視点ベクトルを求める
                    nViewVectX = arViewVertex[ mCurr.arPolygon[j][0] ][0];
                    nViewVectY = arViewVertex[ mCurr.arPolygon[j][0] ][1];
                    nViewVectZ = arViewVertex[ mCurr.arPolygon[j][0] ][2] + nFocus; 
                
                    // 法線ベクトルと視点ベクトルの内積を求める
                    nInnerProduct = arNormal[j][0]*nViewVectX + arNormal[j][1]*nViewVectY + arNormal[j][2]*nViewVectZ;
                    
                    //m.lineStyle( mCurr.nEdgeSize, mCurr.nEdgeColor );
                    if ( nInnerProduct > 0 ) {
                        // 光線の方向ベクトルと法線ベクトルのなす余弦(cos)を計算
                        nCos = (arNormal[j][0]*nLightX + arNormal[j][1]*nLightY + arNormal[j][2]*nLightZ )
                            / Math.sqrt(arNormal[j][0]*arNormal[j][0] + arNormal[j][1]*arNormal[j][1] + arNormal[j][2]*arNormal[j][2] ) / nLightLength;
                        if ( nCos < 0 )  nCos = 0;
                        nRef = 0.3 * nCos + 0.7;
                        
                        // 反射率からポリゴンの色を計算
                        nR = Math.floor((mCurr.nPolygonColor >>> 16)  * nRef);
                        nG = Math.floor(((mCurr.nPolygonColor & 0x00FFFF) >>> 8 ) * nRef);
                        nB = Math.floor((mCurr.nPolygonColor & 0x0000FF) * nRef);
                        nColor = nR * 0x010000 + nG * 0x000100 + nB;
                        
                        m.lineStyle( mCurr.nEdgeSize, mCurr.nEdgeColor, 0 );
                        m.moveTo( arScrVertex[arPolygon[j][0]][0], -arScrVertex[arPolygon[j][0]][1]);
                        m.beginFill( nColor, 100);
                        for (k=1; k<mCurr.arPolygon[j].length; k++)
                            m.lineTo(arScrVertex[arPolygon[j][k]][0], -arScrVertex[arPolygon[j][k]][1]);
                        m.lineTo( arScrVertex[arPolygon[j][0]][0], -arScrVertex[arPolygon[j][0]][1]);
                        m.endFill();
                    }
                }
            }
        }
        
        //透視投影でモデルを表示
        public function draw(m:Graphics):void {
            var i:int, j:int, k:int;
            var mCurr:Model;                      // 現在描写しているモデル
            var arScrVertex:Array = [];       // スクリーン座標系での頂点の座標値
            var nScrX:Number, nScrY:Number;
            var arNormal:Array;
            var nInnerProduct:Number;
            var nViewVectX:Number, nViewVectY:Number, nViewVectZ:Number;  // 視点から頂点へのベクトル
            var nTotalZ:Number;
            var nLightX:Number, nLightY:Number, nLightZ:Number, nLightLength:Number; // 光線の方向ベクトル
            var nRef:Number;
            var nCos:Number;
            var nColor:Number, nR:Number, nG:Number, nB:Number;
            
            var arViewVertex:Array, arPolygon:Array;
            
            // カメラ座標系における光線の方向ベクトルを求める
            mLight.arViewVertex =  viewingTransform(mLight); 
            nLightX = mLight.arViewVertex[0][0] - mLight.arViewVertex[1][0];
            nLightY = mLight.arViewVertex[0][1] - mLight.arViewVertex[1][1];
            nLightZ = mLight.arViewVertex[0][2] - mLight.arViewVertex[1][2];
            nLightLength = Math.sqrt( nLightX*nLightX + nLightY*nLightY + nLightZ*nLightZ );
            
            // 視野変換を行い、奥にあるものから順に並ぶようにモデルをソートする 
            for ( i=0; i<arModels.length; i++ ) {
                mCurr =  arModels[i];
                // 視野変換
                mCurr.arViewVertex = viewingTransform(mCurr);
                // 重心の z 座標を計算
                nTotalZ = 0;
                for ( j=0; j<mCurr.arViewVertex.length; j++ ) 
                    nTotalZ += mCurr.arViewVertex[j][2];
                mCurr.nCenterZ = nTotalZ / mCurr.arViewVertex.length;
            }
            arModels.sortOn("nCenterZ", Array.NUMERIC );
            
            // 後方にあるモデルから順に描画
            for (i=arModels.length-1; i>=0; i--) {
                mCurr = arModels[i];
                arViewVertex = mCurr.arViewVertex;
                arPolygon = mCurr.arPolygon;
                
                // 投影変換
                for (j=0; j<mCurr.arVertex.length; j++) {
                    nScrX = nFocus*arViewVertex[j][0] / (  arViewVertex[j][2]  );
                    nScrY = nFocus*arViewVertex[j][1] / (  arViewVertex[j][2]  );
                    arScrVertex[j] = [nScrX, nScrY];
                }
                
                // 各ポリゴンの法線ベクトルを求める
                arNormal = calcNormal(mCurr);
                    
                for ( j=0; j<mCurr.arPolygon.length; j++ ) {
                    if ( mCurr.nType == Model.NULL ) continue;
                    // 視点ベクトルを求める
                    nViewVectX = arViewVertex[ mCurr.arPolygon[j][0] ][0];
                    nViewVectY = arViewVertex[ mCurr.arPolygon[j][0] ][1];
                    nViewVectZ = arViewVertex[ mCurr.arPolygon[j][0] ][2]; 
                
                    // 法線ベクトルと視点ベクトルの内積を求める
                    nInnerProduct = arNormal[j][0]*nViewVectX + arNormal[j][1]*nViewVectY + arNormal[j][2]*nViewVectZ;
                    
                    if ( nInnerProduct > 0 ) {
                        // 光線の方向ベクトルと法線ベクトルのなす余弦(cos)を計算
                        nCos = (arNormal[j][0]*nLightX + arNormal[j][1]*nLightY + arNormal[j][2]*nLightZ )
                            / Math.sqrt(arNormal[j][0]*arNormal[j][0] + arNormal[j][1]*arNormal[j][1] + arNormal[j][2]*arNormal[j][2] ) / nLightLength;
                        if ( nCos < 0 )  nCos = 0;
                        nRef = 0.3 * nCos + 0.7;
                        
                        // 反射率からポリゴンの色を計算
                        nR = Math.floor((mCurr.nPolygonColor >>> 16)  * nRef);
                        nG = Math.floor(((mCurr.nPolygonColor & 0x00FFFF) >>> 8 ) * nRef);
                        nB = Math.floor((mCurr.nPolygonColor & 0x0000FF) * nRef);
                        nColor = nR * 0x010000 + nG * 0x000100 + nB;
                        
                        // モデルのタイプに応じて線を描くか否かを決める
                        if ( mCurr.nType == Model.POLYGON ) {
                            m.lineStyle( mCurr.nEdgeSize, mCurr.nEdgeColor, 0 );
                        }
                        else 
                            m.lineStyle( mCurr.nEdgeSize, mCurr.nEdgeColor, 100 );
                            
                        m.moveTo( arScrVertex[arPolygon[j][0]][0], -arScrVertex[arPolygon[j][0]][1]);
                        m.beginFill( nColor );
                        for (k=1; k<mCurr.arPolygon[j].length; k++)
                            m.lineTo(arScrVertex[arPolygon[j][k]][0], -arScrVertex[arPolygon[j][k]][1]);
                        m.lineTo( arScrVertex[arPolygon[j][0]][0], -arScrVertex[arPolygon[j][0]][1]);
                        m.endFill();
                    }
                }
            }
        }
        
        // 視野変換を行う
        private function viewingTransform(model:Model):Array {
            var arViewVertex:Array = new Array();
            var nCosA:Number, nCosB:Number,nSinA:Number, nSinB:Number, nSinA_SinB:Number, nSinA_CosB:Number, nCosA_CosB:Number, nCosA_SinB:Number, nTemp1:Number, nTemp2:Number;
            var nX:Number, nY:Number, nZ:Number;
            var i:int, j:int;
            
            var arVertex:Array = model.arVertex;
            
            var vlx:Number = nViewpointX - nLookingpointX;
            var vly:Number = nViewpointY - nLookingpointY;
            var vlz:Number = nViewpointZ - nLookingpointZ;
            
            
            nTemp1 = Math.sqrt(vlx*vlx + vlz*vlz);
            nTemp2 = Math.sqrt(vlx*vlx+ vly*vly + vlz*vlz);
            nCosA = vlz / nTemp1;
            nSinA = -vlx / nTemp1;
            nCosB = nTemp1 / nTemp2;
            nSinB = vly / nTemp2;
            
            nSinA_SinB = nSinA * nSinB;
            nSinA_CosB = nSinA * nCosB;
            nCosA_SinB = nCosA * nSinB;
            nCosA_CosB = nCosA * nCosB;
            
            for ( i=0; i<arVertex.length; i++) {
                nX = arVertex[i][0];
                nY = arVertex[i][1];
                nZ = arVertex[i][2];
                arViewVertex[i] = [
                           nCosA*(nX - nViewpointX) + nSinA*(nZ - nViewpointZ),
                           nSinA_SinB*(nX - nViewpointX) + nCosB*(nY - nViewpointY) - nCosA_SinB*(nZ - nViewpointZ),
                           nSinA_CosB*(nX - nViewpointX) - nCosA_CosB*(nZ  - nViewpointZ) - nSinB*(nY - nViewpointY)
                    ];
            }
            
            return arViewVertex;
        }
        
        // カメラ座標系における各ポリゴンの法線ベクトルの計算
        private function calcNormal(model:Model):Array {
            var i:int;
            var ax:Number, ay:Number, az:Number, bx:Number, by:Number, bz:Number, nx:Number, ny:Number, nz:Number, abs:Number;
            var arNormal:Array = new Array();
            var arViewVertex:Array = model.arViewVertex;
            var arPolygon:Array = model.arPolygon;
            var nPolygonLength:Number = model.arPolygon.length;
            
            for (i=0; i<nPolygonLength; i++) {
                ax = arViewVertex[arPolygon[i][2]][0] - arViewVertex[arPolygon[i][1]][0];
                ay = arViewVertex[arPolygon[i][2]][1] - arViewVertex[arPolygon[i][1]][1];
                az = arViewVertex[arPolygon[i][2]][2] - arViewVertex[arPolygon[i][1]][2];
                bx = arViewVertex[arPolygon[i][1]][0] - arViewVertex[arPolygon[i][0]][0];
                by = arViewVertex[arPolygon[i][1]][1] - arViewVertex[arPolygon[i][0]][1];
                bz = arViewVertex[arPolygon[i][1]][2] - arViewVertex[arPolygon[i][0]][2];
                nx = ay*bz - az*by;
                ny = az*bx - ax*bz;
                nz = ax*by - ay*bx;
                //abs = Math.sqrt( nx*nx + ny*ny + nz*nz );
                //arNormal[i]  = [nx/abs, ny/abs, nz/abs];
                arNormal[i]  = [nx, ny, nz];
            }
            return arNormal;
        }
    }
//}


//package simple3d {
    /*public*/ class Model {
        public static const WIRE:uint = 0;
        public static const POLYGON:uint = 1;
        public static const WIRE_POLYGON:uint = 2;
        public static const NULL:uint = 3;
        
        public var arVertex :Array;        // 頂点の座標
        public var arEdge:Array;            // 辺情報
        public var arPolygon:Array;        // 面情報
        public var nCenterZ:Number;    // 重心のZ座標
        public var arViewVertex:Array; // 視野変換後の頂点の座標
        public var nEdgeColor:Number;    // 辺の色
        public var nEdgeSize:Number;   // 辺の太さ
        public var nPolygonColor:Number; // ポリゴンの色
        public var nType:Number;         // ワイヤーフレーム表示かポリゴン表示かを指定
        
        // コンストラクタ
        public function Model(t:uint) {
            nEdgeColor = 0x000000;
            nPolygonColor = 0xffffff;
            nEdgeSize = 0;
            nType = t;
        }
        
        // 頂点情報の登録
        public function setVertex(v:Array):void {
            arVertex = v;
        }
        
        // 辺情報の登録
        public function setEdge(e:Array):void {
            arEdge = e;
        }
        
        // ポリゴン情報の登録
        public function setPolygon(p:Array):void {
            arPolygon = p;
        }
        
        // 辺の色の設定
        public function setEdgeColor(nColor:Number):void {
            nEdgeColor = nColor;
        }
        
        // ポリゴンの色の設定
        public function setPolygonColor(nColor:Number):void {
            nPolygonColor = nColor;
        }
        
        // 辺の太さの設定
        public function setEdgeSize(nSize:Number):void {
            nEdgeSize = nSize;
        }
        
        // ワイヤーフレーム表示 / ポリゴン表示の変更
        public function setTYpe(t:Number):void {
            nType = t;
        }
        
        // モデルを伸縮する
        public function scale(x:Number, y:Number, z:Number):void {
            var i:int;
            var nLength:Number = arVertex.length;
            var arTemp:Array = arVertex;
            
            for (i=0; i<nLength; i++) {
                arTemp[i][0] *= x;
                arTemp[i][1] *= y;
                arTemp[i][2] *= z;
            }
        }
        
        // モデルを平行移動する
        public function translate(x:Number, y:Number, z:Number):void {
            var i:int;
            var nLength:Number = arVertex.length;
            var arTemp:Array = arVertex;
            
            for (i=0; i<nLength; i++) {
                arTemp[i][0] += x;
                arTemp[i][1] += y;
                arTemp[i][2] += z;
            }
        }
        
        // モデルを回転移動する
        public function rotate(a:Number, b:Number, c:Number):void {
            var i:int;
            var y1:Number, z1:Number, x2:Number;
            var nLength:Number = arVertex.length;
            var arTemp:Array = arVertex;
            var sin_a:Number, cos_a:Number, sin_b:Number, cos_b:Number, sin_c:Number, cos_c:Number;
            
            a = a * Math.PI / 180;
            b = b * Math.PI / 180;
            c = c * Math.PI / 180;
            
            sin_a = Math.sin(a);
            cos_a = Math.cos(a);
            sin_b = Math.sin(b);
            cos_b = Math.cos(b);
            sin_c = Math.sin(c);
            cos_c = Math.cos(c);
            
            for (i=0; i<nLength; i++) {
                y1 = arTemp[i][1] * cos_a - arTemp[i][2] * sin_a;
                z1 = arTemp[i][1] * sin_a + arTemp[i][2] * cos_a;
            
                x2 = arTemp[i][0] * cos_b + z1 * sin_b;
                arTemp[i][2]  = -arTemp[i][0]  * sin_b + z1 * cos_b;
            
                arTemp[i][0]  = x2 * cos_c - y1 * sin_c;
                arTemp[i][1]  = x2 * sin_c + y1 * cos_c;
            }
        }
    }
//}

//package simple3d {
    /*internal*/ class Light extends Model {
        public function Light(x:Number, y:Number, z:Number) {
            super(0);
            
            arVertex = [[0,0,0], [x, y, z]];
        }
    }
//}

//package simple3d {
    /*public*/ class Cube extends Model {
        public function Cube(type:int, size:Number) {
            super(type);
            
            size /=2;
            arVertex = [ 
                [-size, size, -size],
                [size, size, -size],
                [size, size, size],
                [-size, size, size],
                [-size,-size, -size],
                [size,-size, -size],
                [size,-size, size],
                [-size,-size, size]
            ];
                    
            arEdge = [
                [ 0, 1, 2, 3, 0, 4, 5, 6, 7, 4],
                [1, 5], 
                [2, 6],
                [3, 7] 
            ];
                    
            arPolygon = [ 
                [ 0, 1, 2, 3 ],
                [ 4, 7, 6, 5 ],
                [ 0, 4, 5, 1 ],
                [ 3, 2, 6, 7 ],
                [ 0, 3, 7, 4 ],
                [ 1, 5, 6, 2 ]
            ];
        }
    }
//}

//package simple3d {
    /*public*/ class Sphere extends Model {
        public function Sphere(radius:Number, slices:Number, stacks:Number, type:uint=Model.POLYGON) {
            super(type);
            
            var i:int,j:int;
            var y:Number = radius;
            var x:Number, z:Number;
            var arTemp:Array;
            var r:Number
            
            if ( slices < 1 ) slices = 1;
            if ( stacks < 3 ) stacks = 3;
            
            // 頂点データの作成
            arVertex = [
                        [0, radius, 0]
                        ];
            
            for ( i=0; i<slices; i++) {
                //y = y - 2*radius/(slices+1);
                y = radius * Math.cos((Math.PI/(slices+1))*(i+1));
                for (j=0; j<stacks; j++) {
                    r = Math.sqrt(radius*radius - y*y);
                    x = r*Math.cos((2*Math.PI/stacks)*j);
                    z = r*Math.sin((2*Math.PI/stacks)*j);
                    arVertex.push([x, y, z]);
                }
            }
            arVertex.push([0, -radius, 0]);
            
            arEdge = new Array();
            arTemp = new Array();
            
            // 辺データの作成
             for ( i=0; i<slices; i++ ) {
                 for (j=i*stacks+1; j<=(i+1)*stacks; j++) {
                     arTemp.push(j);
                 }
                 arTemp.push(i*stacks+1);
                 arEdge.push(arTemp);
                 arTemp = new Array();
             }
             for (i=1; i<=stacks; i++) {
                 arTemp.push(0);
                 for (j=0; j<slices; j++) {
                     arTemp.push( i + j*stacks );
                 }
                 arTemp.push(arVertex.length - 1);
                 arEdge.push(arTemp);
                 arTemp = new Array();
             }
             
             // 面データの作成
             arPolygon = new Array();
             
             for ( i=1; i<=stacks; i++) {
                 if (i != stacks) arPolygon.push([0, i+1, i]);
                 else arPolygon.push([0, 1, i]);
             }
             for ( i=0; i<slices-1; i++ ) {
                 for ( j=1; j<=stacks; j++ ) {
                     if ( j != stacks ) arPolygon.push([i*stacks+j, i*stacks+j+1, (i+1)*stacks+j+1, (i+1)*stacks+j]);
                     else arPolygon.push([i*stacks+j, i*stacks+1, (i+1)*stacks+1, (i+1)*stacks+j]);
                 }
             }
             for ( i=(slices-1)*stacks+1; i<=stacks*slices; i++) {
                 if (i != stacks*slices) arPolygon.push([stacks*slices+1, i, i+1]);
                 else arPolygon.push([stacks*slices+1, i, (slices-1)*stacks+1]);
             }
        }
    }
//}