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

forked from: That flower (stage3d)

Thatflower(use stage3d)
まだ高速化は意識してないです。

...
@author okoi
Get Adobe Flash player
by es335dotr 18 Nov 2011
/**
 * Copyright es335dotr ( http://wonderfl.net/user/es335dotr )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/vczL
 */

// forked from okoi's That flower (stage3d)
/**
 * Thatflower(use stage3d)
 *     まだ高速化は意識してないです。
 */
package 
{
    import com.adobe.utils.AGALMiniAssembler;
    import com.adobe.utils.PerspectiveMatrix3D;
    import flash.display.Stage3D;
    import flash.display3D.Program3D;
    import flash.display3D.Context3D;
    import flash.display3D.Context3DRenderMode;
    import flash.display3D.Context3DVertexBufferFormat;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.Context3DTriangleFace;    
    import flash.display3D.Context3DBlendFactor;
    import flash.display3D.Context3DCompareMode;
    
    import flash.display.Sprite;
    import flash.events.Event;
    import flash.geom.Matrix3D;
    import flash.utils.ByteArray;
    import flash.geom.Vector3D;
    
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    
    [SWF(width="900", height="600", frameRate="60")]
    
    /**
     * ...
     * @author okoi
     */
    public class Main extends Sprite 
    {
        public static const CAPTURE:Boolean = false;
        private var _captureBmd:BitmapData;
        
        
        public static const WIDTH:int = 465;
        public static const HEIGHT:int = 465;
                        
        private var _stage3D:Stage3D;
        private var _context3D:Context3D;
        private var _renderProgram:Program3D;    //    レンダリングプログラム
        
        private var _matProjection:PerspectiveMatrix3D;
        private var _camera:Camera;

        private var _flower:Flower;
        private var _particleList:Vector.<Particle>;
        
        private var _ct:uint = 0;
        
        
        public function Main():void 
        {
            Wonderfl.disable_capture();            
            
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);
        }
        
        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            // entry point
            _stage3D = stage.stage3Ds[0];
            _stage3D.addEventListener( Event.CONTEXT3D_CREATE, Context3DCreateHandler );
            _stage3D.requestContext3D( Context3DRenderMode.AUTO );
            
            if ( CAPTURE ) {
                _captureBmd = new BitmapData(WIDTH, HEIGHT, true, 0);
                addChild( new Bitmap( _captureBmd ) );
            }
        }
        
        private function Context3DCreateHandler( e:Event ) : void 
        {
            _context3D = _stage3D.context3D;
            _context3D.enableErrorChecking = true;
            _context3D.configureBackBuffer( WIDTH, HEIGHT, 4, true );
            _context3D.setCulling(Context3DTriangleFace.BACK);
            _context3D.setBlendFactors( Context3DBlendFactor.SOURCE_ALPHA, Context3DBlendFactor.ONE_MINUS_SOURCE_ALPHA );
            _context3D.setDepthTest(false, Context3DCompareMode.ALWAYS);
            _renderProgram = _context3D.createProgram();
            
            InitCamera();
            InitProjection();
            InitShader();
            
            InitFlowerData();
            
            _context3D.clear();
                                                
            addEventListener( Event.ENTER_FRAME, EnterFrameHandler );
        }        
        
        private function InitProjection() : void {
            
            _matProjection = new PerspectiveMatrix3D();
            _matProjection.perspectiveFieldOfViewLH( 45 * Math.PI / 180, WIDTH / HEIGHT, 0.1, 3000 );
        }
        
        /**
         * カメラの初期化を行う
         */
        private function InitCamera() : void {
            _camera = new Camera();        
        }
        
        private function InitShader() : void {
            
            var agalAssembler:AGALMiniAssembler = new AGALMiniAssembler();

            var code:String = "";
            var vShader:ByteArray;
            var fShader:ByteArray;
            
            code =  "m44 op, va0, vc0\n";
            code += "mov v0, va1\n";
            vShader = agalAssembler.assemble( Context3DProgramType.VERTEX, code );
            
            code = "tex ft0, v0, fs0 <2d,clamp,linear>\n";
            code += "mul oc, ft0, fc0\n";
            fShader = agalAssembler.assemble( Context3DProgramType.FRAGMENT, code );
            
            _renderProgram.upload( vShader, fShader );
            _context3D.setProgram(_renderProgram);
        }        
        
        private function EnterFrameHandler( e:Event ) : void {
            
            
            var i:int;
            
            //--------------------------
            //    カメラの回転
            var cameraAngle:Number = ((_ct * 0.1) + 90) % 360; 
            var cR:Number = Math.sin( ((_ct * 0.2) % 360) * Math.PI / 180 ) * 0; // 酔うかもw
            var cameraX:Number = Math.cos( cameraAngle * Math.PI / 180 ) * (5 + cR);
            var cameraZ:Number = Math.sin( cameraAngle * Math.PI / 180 ) * (5 + cR);                        
            _camera.InitView( new Vector3D(cameraX, 0, -cameraZ), new Vector3D(0, 0, 0), new Vector3D(0, 1, 0) );

            //--------------------------
            //    パーティクルの移動と描画順ソート処理
            for ( i = _particleList.length - 1; i >= 0; i-- ) {
                if ( _particleList[i].life > 0 ) {
                    _particleList[i].Update( _camera );
                } else {
                    _particleList.splice( i, 1 );
                }
            }
            _particleList.sort( SortFlower );
            
            //--------------------------
            //    ポリゴンレンダリング
            _context3D.clear(1,1,1,1);        
            for ( i = _particleList.length - 1; i >= 0; i-- ){
                var mat:Matrix3D = new Matrix3D();
                var particle:Particle = _particleList[i];
                
                _context3D.setVertexBufferAt( 0, _flower.vBuf, 0, Context3DVertexBufferFormat.FLOAT_3 );    //    va0
                _context3D.setVertexBufferAt( 1, _flower.uvBuf, 0, Context3DVertexBufferFormat.FLOAT_2 );    //    va1
                _context3D.setTextureAt( 0, _flower.texture );
            
                mat.append( particle.matrix );    //    ワールド座標変換
                mat.append( _camera.matrix );    //    ビュー変換変換
                mat.append( _matProjection );    //    プロジェクション座標変換
                
                var alpha:Number = 0;
                if ( particle.lifeRate < 0.1 )    alpha = particle.lifeRate * 10;
                else if ( particle.lifeRate < 0.9 )    alpha = 1;
                else                             alpha = (1 - particle.lifeRate) * 10;
                
                _context3D.setProgramConstantsFromMatrix( Context3DProgramType.VERTEX, 0, mat, true );    //    vc0    
                _context3D.setProgramConstantsFromVector( Context3DProgramType.FRAGMENT, 0, Vector.<Number>([ particle.r, particle.g, particle.b, alpha ]) );
                _context3D.drawTriangles( _flower.iBuf );
            }    
            
            if ( CAPTURE ) {
                _context3D.drawToBitmapData( _captureBmd );
            }
            
            _context3D.present();
            
            //--------------------------
            //    パーティクル追加
            addFlower();
            addFlower();
            
            //
            _ct++;            
        }
        
        private function InitFlowerData() : void {
            
            _flower = new Flower( _context3D );
            _particleList = new Vector.<Particle>();
        
        }
        
        private function addFlower() : void {
                        
            var particle:Particle = new Particle();
            var i:int = 0;
            for ( i = 0; i < _particleList.length; i++ ) {
                if ( particle.z <= _particleList[i].z ) {
                    break;
                }
            }
            _particleList.splice( i, 0, particle );
            
        }
        
        private function SortFlower( a:Particle, b:Particle ) : int {
            if ( a.viewz == b.viewz )    return    0;
            if ( a.viewz > b.viewz )    return    1;
            return -1;            
        }
    }
    
}
import flash.display.BitmapData;
import flash.display.Shape;
import flash.display3D.Context3D;
import flash.display3D.textures.Texture;
import flash.display3D.IndexBuffer3D;
import flash.display3D.VertexBuffer3D;
import flash.display3D.Context3DTextureFormat;
import flash.geom.Matrix;
import flash.geom.Matrix3D;
import flash.geom.Vector3D;

class Camera {
    private var _view:Matrix3D;
    private var _from:Vector3D;
    private var _at:Vector3D;
    private var _up:Vector3D;
    
    public function Camera() {
        
        _view = new Matrix3D();
    }
    
    /**
     * ビュー行列の設定を行う
     * PerspectiveMatrix3DのlookAtLH,RHはバグがあるっぽいので自力計算
     * @param    from
     * @param    at
     * @param    up
     */
    public function InitView( from:Vector3D, at:Vector3D, up:Vector3D ) : void {

        var vz:Vector3D = at.subtract( from );
        vz.normalize();
        var vx:Vector3D = up.crossProduct( vz );
        vx.normalize();
        var vy:Vector3D = vz.crossProduct( vx );
        vy.normalize();
        var vtx:Number = vx.dotProduct( from ) * -1;
        var vty:Number = vy.dotProduct( from ) * -1;
        var vtz:Number = vz.dotProduct( from ) * -1;
        
        _view.identity();
        _view.rawData = Vector.<Number>([
            vx.x, vy.x, vz.x, 0,
            vx.y, vy.y, vz.y, 0,
            vx.z, vy.z, vz.z, 0,
            vtx,  vty,  vtz,  1,
        ]);        
        
        _from = from;
        _at = at;
        _up = up;
    }
    
    public function get matrix():Matrix3D {
        return    _view;
    }
    
    public function get from() : Vector3D {
        return    _from;
    }
    public function get at() : Vector3D {
        return    _at;
    }
}

class Flower {
    public static const TEX_WIDTH:int = 64;
    public static const TEX_HEIGHT:int = 64;
    
    //    各花びらの1枚の専有角度
    public static const PETALANGLE:Array = [ 62, 82, 72, 72, 72 ];
    //    花びら1枚に対しての各クォーターの専有角度率
    public static const QUARTERRATE:Array = [ 0.3, 0.15, 0.25, 0.3 ];
    
    
    private var _vBuf:VertexBuffer3D;
    private var _uvBuf:VertexBuffer3D;
    private var _iBuf:IndexBuffer3D;
    
    private var _texture:Texture;
    
    public function Flower( context3d:Context3D ) {
        
        _vBuf = context3d.createVertexBuffer( 4, 3 );
        _vBuf.uploadFromVector( 
            Vector.<Number>([
                -0.1,  0.1, 0,
                 0.1,  0.1, 0,
                 0.1, -0.1, 0,
                -0.1, -0.1, 0,
            ]),
            0,
            4
        );
        
        _uvBuf = context3d.createVertexBuffer( 4, 2 );
        _uvBuf.uploadFromVector( 
            Vector.<Number>([
                0,  0,
                1,  0,
                1,  1,
                0,  1,
            ]),
            0,
            4
        );
        
        _iBuf = context3d.createIndexBuffer( 3 * 2 );
        _iBuf.uploadFromVector(
            Vector.<uint>([
                0, 1, 2,
                2, 3, 0,
            ]),
            0,
            3 * 2
        );
        
        InitTexture( context3d );
    }
    
    private function InitTexture( context3d:Context3D ) : void {
        
        var w:int = TEX_WIDTH;
        var h:int = TEX_HEIGHT;
        var radius:Number = 25;
        var i:int, p:int;
        var tmp1:int, tmp2:int;
        var t1:Number, t2:int;
        var sin45:Number = Math.sin( 45 * Math.PI / 180 );
        
        var shape:Shape = new Shape();
        shape.graphics.beginFill( 0xFFFFFF );
                
       // 花びら1枚1枚のパラメータを決定する
        var petalAngles:Array = PETALANGLE;
        var rOffset:Array = [];
        var rOffset2:Array = [];
        for ( p = 0; p < 4; p++ ) {
            rOffset.push( Math.random() * 0.2 - 0.1 + 0.5 );
            rOffset2.push( Math.random() * 0.2 + 0.8 );
        }
        rOffset.push( Math.random() * 0.2 - 0.1 + 0.5 );
        rOffset2.push( Math.random() * 0.2 + 0.8 );

        // 各クォーターの専有角度
        var quarterRate:Array = QUARTERRATE;

        // 花びら1枚1枚描画していく(5枚分)
        var startAngle:int = 0;
        for ( p = 0; p < 5; p++ ) {
            for ( i = 0; i <= petalAngles[p]; i++ ) {

                var rad:Number = (startAngle + i) * Math.PI / 180;
                // 基本位置
                var x:Number = Math.cos( rad ) * radius;
                var y:Number = Math.sin( rad ) * radius;

                //
                var quarter:int;
                var quarterStartRate:Number = 0;
                var nowrate:Number = i / petalAngles[p];
                t1 = 0;
                for ( quarter = 0; quarter < 4; quarter++ ) {
                    t1 += quarterRate[quarter];
                    if ( nowrate < t1 ) {
                        break;
                    }
                    quarterStartRate += quarterRate[quarter];
                }
                quarter %= 4;

                var r:Number;
                var rate:Number = (nowrate - quarterStartRate) / quarterRate[quarter];
                rate *= 90; // 1Qで90度分の角度変化を行う

                // Q-0
                // startY 0
                // endY sin45θ
                if ( quarter == 0 ) {
                    rad = (rate) * Math.PI / 180;
                    r = Math.abs( Math.sin( rad ) ) * sin45;
                }
                // Q-1
                // startY sin45θ
                // endY sin90θ
                if ( quarter == 1 ) {
                    rad = (rate + 90) * Math.PI / 180;
                    //trace( Math.abs( Math.sin( rad ) ) );
                    r = (1 - Math.abs( Math.sin( rad ) ) ) * (1 - sin45) * 0.4 + sin45;
                }
                // Q-2
                // startY sin90θ
                // endY sin45θ
                if ( quarter == 2 ) {
                rad = rate * Math.PI / 180;
                r = (1 - Math.abs( Math.sin( rad ) )) * (1 - sin45) * 0.4 + sin45;

                }
                // Q-3
                // startY sin45θ
                // endY 0
                if ( quarter == 3 ) {
                    rad = (rate + 90) * Math.PI / 180;
                    r = Math.abs( Math.sin( rad ) ) * sin45;
                }

                //
                r += rOffset[p];
                x *= r;
                y *= r * 0.9;

                if ( p == 0 && i == 0 ) shape.graphics.moveTo(x, y);
                else shape.graphics.lineTo(x, y);
            }
            startAngle += petalAngles[p];
            
        }
        shape.graphics.endFill();        
        
        
        
        
        var bmd:BitmapData = new BitmapData(w, h, true, 0 );
        bmd.draw( shape, new Matrix(1, 0, 0, 1, w/2, h/2), null, null, null, true  );
        
        _texture = context3d.createTexture( w, h, Context3DTextureFormat.BGRA, false );
        _texture.uploadFromBitmapData( bmd );
        
        bmd.dispose();
        bmd = null;
    }    
    public function get vBuf():VertexBuffer3D { return    _vBuf;    }
    public function get uvBuf():VertexBuffer3D { return _uvBuf;    }
    public function get iBuf():IndexBuffer3D { return    _iBuf;    }
    public function get texture():Texture { return    _texture;    }

}

class Particle {
    public var x:Number = 0;
    public var y:Number = 0;
    public var z:Number = 0;
    public var angle:Number = 0;
    public var rotationY:Number = 0;
    
    public var vy:Number = 0;

    public var r:Number = 1;
    public var g:Number = 1;
    public var b:Number = 1;
    
    public var life:uint;
    public var maxlife:uint;
    
    public var viewz:Number = 0;
    
    public function Particle() {
        life = Math.random() * 300 + 400;
        maxlife = life;
        
        var temp:Number = Math.random() * 360;
        var temp2:Number = Math.random() * 10;
                    
        x = Math.cos( temp * Math.PI / 180 ) * temp2;
        y = -3;
        z = Math.sin( temp * Math.PI / 180 ) * temp2;
        
        vy = 0.01 + Math.random() * 0.001;
        
        temp = int(Math.random() * 5);
        switch( temp ) {
        case 0:    r = 0xF4 / 0xFF; g = 0x7E / 0xFF; b = 0xB9 / 0xFF;    break;
        case 1:    r = 0xFF / 0xFF; g = 0x7D / 0xFF; b = 0x69 / 0xFF;    break;
        case 2:    r = 0xFB / 0xFF; g = 0xD1 / 0xFF; b = 0xDC / 0xFF;    break;
        case 3:    r = 0xF6 / 0xFF; g = 0x5A / 0xFF; b = 0x67 / 0xFF;    break;
        case 4:    r = 0xF9 / 0xFF; g = 0xE1 / 0xFF; b = 0xBE / 0xFF;    break;
        }        
    }    
    
    public function get matrix() : Matrix3D {
        var mat:Matrix3D = new Matrix3D();
        mat.appendRotation( angle, new Vector3D(0, 0, 1) );
        mat.appendRotation( rotationY, new Vector3D(0, 1, 0) );
        mat.appendTranslation( x, y, z );
        return    mat;
    }    
    
    public function get lifeRate() : Number {
        return    life / maxlife;
    }
    
    public function Update( camera:Camera ) : void {
        angle += 0.4;
        angle %= 360;
        y += vy;
        
        var mat:Matrix3D = this.matrix;
        mat.append( camera.matrix );
        viewz = mat.position.z;
        
        //---------------------------------
        //    向きをカメラの方に向ける計算
        var zvec:Vector3D = new Vector3D( 0, 0, 1 );
        var cameraVec:Vector3D = new Vector3D( camera.at.x - camera.from.x, 0, camera.at.z - camera.from.z );
        cameraVec.normalize();
        
        var dot:Number = zvec.dotProduct( cameraVec );
        var rad:Number = Math.acos( dot / (cameraVec.length * 1/*zvec.length*/) );
        var cross:Vector3D = zvec.crossProduct( cameraVec );
        if ( cross.y < 0 )    rad *= -1;
        rotationY = rad * 180 / Math.PI;
        
        life--;
    }
}