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

Annular Eclipse Stage3D

時事ネタということで、Stage3Dで金環日食っぽいのを作ってみました。
マウスのY座標で光の強さを変えられます。
Get Adobe Flash player
by yuichiroharai 21 May 2012
/**
 * Copyright yuichiroharai ( http://wonderfl.net/user/yuichiroharai )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/eNkj
 */

package 
{
    import com.adobe.utils.AGALMiniAssembler;
    import com.adobe.utils.PerspectiveMatrix3D;
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.display.Stage3D;
    import flash.display.StageAlign;
    import flash.display.StageQuality;
    import flash.display.StageScaleMode;
    import flash.display3D.Context3D;
    import flash.display3D.Context3DBlendFactor;
    import flash.display3D.Context3DCompareMode;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.Context3DRenderMode;
    import flash.display3D.Context3DTriangleFace;
    import flash.display3D.Context3DVertexBufferFormat;
    import flash.display3D.IndexBuffer3D;
    import flash.display3D.Program3D;
    import flash.display3D.VertexBuffer3D;
    import flash.events.Event;
    import flash.geom.Matrix3D;
    import flash.geom.Vector3D;
    import flash.utils.getTimer;
    import net.hires.debug.Stats;
    
    [SWF(width="465", height="465", backgroundColor="0x000000")]
    public class AnnularEclipse extends Sprite 
    {
        
// ----------------------------------------------------------------------------------------------------
// 変数
//
        // Stage 関連
        private var _stageWidth:uint;
        private var _stageHeight:uint;
        private var _stageWidthHarf:uint;
        private var _stageHeightHarf:uint;
        
        // Stage3D 関連
        static private const _SEGMENT:uint = 128;
        
        private var _stage3D:Stage3D;
        private var _context3D:Context3D;
        private var _stage3DSize:uint;
        private var _vertexList:Vector.<Number>;
        private var _vertexBuffer:VertexBuffer3D;
        private var _indexList:Vector.<uint>;
        private var _indexBuffer:IndexBuffer3D;
        private var _perspectiveMatrix3D:PerspectiveMatrix3D;
        
        private var _time:uint;
        private var _rotationZ:Number = 0;
        private var _power:Number = 0;
        private var _mouseY:Number = 0;
        
        // AGAL 関連
        private var _agalVertex:String;
        private var _agalFragment:String;
        
        // スクリーンショット
        private var _screenShot:Bitmap;
        
// ----------------------------------------------------------------------------------------------------
// コンストラクタ
//    
        // コンストラクタ
        public function AnnularEclipse():void 
        {
            Wonderfl.disable_capture();
            //addChild(_screenShot = new Bitmap());
             
            // ステージ設定
            stage.quality = StageQuality.BEST;
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.frameRate = 60;
            
            // ステージイベント
            stage.addEventListener(Event.FULLSCREEN, _atResize);
            stage.addEventListener(Event.RESIZE, _atResize);
            _atResize();
            
            _initStage3D();
        }
        
// ----------------------------------------------------------------------------------------------------
// ステージイベント
//
        // ステージのリサイズ
        private function _atResize(e:Event=null):void 
        { 
            _stageWidth = stage.stageWidth;
            _stageHeight = stage.stageHeight;
            _stageWidthHarf = uint(_stageWidth/2);
            _stageHeightHarf = uint(_stageHeight/2);
            
            if (_context3D != null) _resizeStage3D();
        }
        
// ----------------------------------------------------------------------------------------------------
// Stage3D
//    
        // Stage3D の初期化
        private function _initStage3D():void 
        {
            _stage3D = stage.stage3Ds[0];
            _stage3D.addEventListener(Event.CONTEXT3D_CREATE, _onContext3dCreate);
            _stage3D.requestContext3D(Context3DRenderMode.AUTO);
        }
        // Stage3D の初期化完了
        private function _onContext3dCreate(e:Event):void
        {
            var model:Model;
            
            // Context3D 初期化
            _context3D = _stage3D.context3D;
            //_context3D.enableErrorChecking = true;
            _context3D.setDepthTest(true, Context3DCompareMode.LESS);
            _context3D.setCulling(Context3DTriangleFace.NONE);
            _context3D.setBlendFactors(Context3DBlendFactor.SOURCE_ALPHA, Context3DBlendFactor.ZERO);
            
            _resizeStage3D();
            _initAgal();
            model = new Model(0.8, _SEGMENT);
            model.color(0xffd700).createIndex();
            
            // VertexBuffer
            _vertexBuffer = _createVertexBuffer(model.vertexList, 8);
            _context3D.setVertexBufferAt(0, _vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_4);
            _context3D.setVertexBufferAt(1, _vertexBuffer, 4, Context3DVertexBufferFormat.FLOAT_4);
            
            // IndexBuffer
            _indexBuffer = _createIndexBuffer(model.indexList);
            
            // 透視投影変換用 Matrix3D
            _perspectiveMatrix3D = new PerspectiveMatrix3D();
            _perspectiveMatrix3D.perspectiveFieldOfViewLH(Math.PI/4, 1, 0.1, 1000);
            
            addEventListener(Event.ENTER_FRAME, _drawStage3D);
        }
        // 毎フレームの描画処理
        private function _drawStage3D(e:Event):void
        {
            var currentTime:uint, matrix3D:Matrix3D, power:Number;
            
            // 時間で回転角度を決定
            _time = (currentTime = getTimer()) - _time;
            if ((_rotationZ += 0.01 * _time) > 360) _rotationZ -= 360;
            if ((_power += 0.1 * _time) > 360) _power -= 360;
            _time = currentTime;
            power = Model.sin(_power * Model.PI2 / 360);
            power = (power * 0.5 + 0.5) * 0.1;
            
            // マウスで変化
            _mouseY += (stage.mouseY/stage.stageHeight - _mouseY)*0.1;
            power += 0.5 * _mouseY;
            
            // 回転の Matrix3D を生成
            matrix3D = new Matrix3D();
            matrix3D.appendRotation(_rotationZ, Vector3D.Z_AXIS);
            matrix3D.appendTranslation(0, 0, 3);
            matrix3D.append(_perspectiveMatrix3D);
            
            // 定数アップロード
            _uploadVertexConstFromMatrix(0, matrix3D);
            _uploadVertexConstFromVector(4, Vector.<Number>([power, 0, 0, 1]))
            
            // 描画
            _context3D.clear(0, 0, 0);
            _context3D.drawTriangles(_indexBuffer, 0);
            //_context3D.drawToBitmapData(_screenShot.bitmapData);
            _context3D.present();
        }
        
        // Stage3D のリサイズ
        private function _resizeStage3D():void {
            // サイズ
            _stage3DSize = (_stageWidth > _stageHeight) ? _stageHeightHarf : _stageWidthHarf;
            _stage3DSize = _stage3DSize * 2; // 偶数になるように調整
            if (_stage3DSize < 466) _stage3DSize = 466;
            
            // 配置
            _stage3D.x = _stageWidthHarf - _stage3DSize/2;
            _stage3D.y = _stageHeightHarf - _stage3DSize/2;
            
            // バッファサイズの初期化
            _context3D.configureBackBuffer(_stage3DSize, _stage3DSize, 16, true);
            
            /*if (_screenShot.bitmapData != null) _screenShot.bitmapData.dispose(); 
            _screenShot.bitmapData = new BitmapData(_stage3DSize, _stage3DSize, false, 0);
            _screenShot.x = _stage3D.x;
            _screenShot.y = _stage3D.y;*/
        }
        
// ----------------------------------------------------------------------------------------------------
// Stage3D - AGAL
//
        private function _initAgal():void
        {
            var vertexAssembler:AGALMiniAssembler, fragmentAssembler:AGALMiniAssembler, program3D:Program3D;
            
            // 頂点シェーダー
            _agalVertex  = "mov vt0, va0 \n";                    // 座標をコピー
            _agalVertex += "mov vt1.w, va0.w \n";                // wを退避
            _agalVertex += "mov vt0.w, vc4.w \n";                // wを1に
            _agalVertex += "mul vt1.w, vt1.w, vc4.x \n";        // 取り出したwに定数をかける
            _agalVertex += "add vt1.w, vt1.w, vc4.w \n";        // 1を足す
            _agalVertex += "mul vt0.xyz, vt0.xyz, vt1.w \n";    // 座標にwをかける
            _agalVertex += "m44 op, vt0, vc0 \n";                // 透視投影変換など
            _agalVertex += "mov v0, va1";
            
            // 断片シェーダー
            _agalFragment = "mov oc, v0";
            
            vertexAssembler = new AGALMiniAssembler();
            vertexAssembler.assemble(Context3DProgramType.VERTEX, _agalVertex);
            fragmentAssembler = new AGALMiniAssembler();
            fragmentAssembler.assemble(Context3DProgramType.FRAGMENT, _agalFragment);
            program3D = _context3D.createProgram();
            program3D.upload(vertexAssembler.agalcode, fragmentAssembler.agalcode);
            _context3D.setProgram(program3D);
        }
        
// ----------------------------------------------------------------------------------------------------
// Stage3D - ユーティリティ
//
        // VertexBufferの生成
        private function _createVertexBuffer(data:Vector.<Number>, numData:int=8):VertexBuffer3D
        {
            var vertexBuffer:VertexBuffer3D, vertexNum:uint;
            
            vertexNum = data.length/numData;
            vertexBuffer = _context3D.createVertexBuffer(vertexNum, numData);
            vertexBuffer.uploadFromVector(data, 0, vertexNum);
            
            return vertexBuffer;
        }
        // IndexBufferの生成・アップロード
        private function _createIndexBuffer(data:Vector.<uint>):IndexBuffer3D
        {
            var indexBuffer:IndexBuffer3D, indexNum:uint;
            
            indexNum = data.length/3;
            indexBuffer = _context3D.createIndexBuffer(data.length);
            indexBuffer.uploadFromVector(data, 0, data.length);
            
            return indexBuffer;
        }
        // Matrix3D から定数のアップロード
        private function _uploadVertexConstFromMatrix(i:uint, data:Matrix3D):void
        {
            _context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, i, data, true);
        }
        // Vector から定数のアップロード
        private function _uploadVertexConstFromVector(i:uint, data:Vector.<Number>):void
        {
            _context3D.setProgramConstantsFromVector(Context3DProgramType.VERTEX, i, data, data.length/4);
        }
        
        
        
        
    }
}

import flash.geom.Matrix3D;
import flash.geom.Rectangle;
import flash.geom.Vector3D;
class Model
{
    public static const PI2:Number = Math.PI*2;
    
    public function get vertexList():Vector.<Number> { return _vertexList; }
    private var _vertexList:Vector.<Number>;
    public function get indexList():Vector.<uint> { return _indexList; }
    private var _indexList:Vector.<uint>;
    
    private var _radius:Number;
    private var _segment:Number;
    private var _segmentPlus:Number;
    
    /**
     * インスタンスを生成
     */
    public function Model(radius:Number, segment:uint=4) {
        _radius = radius;
        _segment = (segment >= 4) ? segment : 4;
        _segmentPlus = _segment + 1;
    }
    
    /**
     * 頂点リストを生成
     */
    public function color(rgb:uint=0xffffff):Model
    {
        var i:uint, angle:Number, fluctuation:Number, x:Number, y:Number, r:Number, g:Number, b:Number;
        
        r = ((rgb >> 16) & 255) / 255;
        g = ((rgb >> 8) & 255) / 255;
        b = (rgb & 255) / 255;
            
        _vertexList = new Vector.<Number>();
        for (i = 0; i < _segmentPlus; i++) {
            angle = i / _segment * PI2;
            fluctuation = sin(i / 4 * PI2);
            
            // 外側
            x = _radius*cos(angle);
            y = _radius*sin(angle);
            _vertexList.push((1.05 + fluctuation * 0.01) * x, (1.05 + fluctuation * 0.01) * y, 0, 1, r, g, b, 0);
            // 中心1
            _vertexList.push(1.00*x, 1.00*y, 0, 0, r, g, b, 1);
            // 中心2
            _vertexList.push(0.98*x, 0.98*y, 0, 0, 1, 1, 1, 1);
            // 内側
            _vertexList.push(0.96*x, 0.96*y, 0, 0, 1, 1, 1, 0);
        }
        return this;
    }
    
    /**
     * インデックスリストを生成
     */
    public function createIndex():Model
    {
        var i:uint;
        
        // インデックスリストにデータを追加
        _indexList = new Vector.<uint>();
        for (i=0;i<_segment;i++) {
            _indexList.push(i*4, (i+1)*4, i*4+1);
            _indexList.push(i*4+1, (i+1)*4, (i+1)*4+1);
            _indexList.push(i*4+1, (i+1)*4+1, i*4+2);
            _indexList.push(i*4+2, (i+1)*4+1, (i+1)*4+2);
            _indexList.push(i*4+2, (i+1)*4+2, i*4+3);
            _indexList.push(i*4+3, (i+1)*4+2, (i+1)*4+3);
        }
        
        return this;
    }
    
    public static function sin(v:Number):Number {
        return Math.round(Math.sin(v) * 1000000000000000) / 1000000000000000;
    }
    public static function cos(v:Number):Number {
        return Math.round(Math.cos(v) * 1000000000000000) / 1000000000000000;
    }
}