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

Particle Video

http://blog.bongiovi.tw/?p=338
/**
 * Copyright bongiovi015 ( http://wonderfl.net/user/bongiovi015 )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/fypQ
 */

package {
    import com.adobe.utils.AGALMiniAssembler;
    import com.adobe.utils.PerspectiveMatrix3D;
    import com.bit101.components.CheckBox;
    import com.bit101.components.ComboBox;
    import com.bit101.components.HSlider;
    import com.bit101.components.Window;
    
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.display3D.Context3D;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.Context3DVertexBufferFormat;
    import flash.display3D.IndexBuffer3D;
    import flash.display3D.Program3D;
    import flash.display3D.VertexBuffer3D;
    import flash.events.Event;
    import flash.geom.Matrix;
    import flash.geom.Matrix3D;
    import flash.geom.Vector3D;
    import flash.utils.ByteArray;
    
    import net.hires.debug.Stats;
    
    [SWF(width=465, height=465, frameRate=30, backgroundColor=0x000000)]
    public class ParticleVideo extends Sprite {
        public var W                    : int;
        public var H                    : int;
        public var context                : Context3D;
        public var depthSort            : Boolean = false;
        public var smoothLevel            : int = 0;  
        public const VIDEO_WIDTH        : int = 360;
        public const VIDEO_HEIGHT        : int = 180;
        public const SCALE                : Number = 2;
        public const INDEX                : Vector.<uint> = Vector.<uint>([0, 1, 2]);
        public const SIZE                : Number = 1;
        public const ROOT3                 : Number = 1.73;
        public const MAX_COLOR_LENGTH    : int = 195075;
        public const MAX                 : int = 20000;
        public const MAX_BUFFER            : int = 16;
        public const OFFSET                : int = 4;
        
        private var fallingSpeed:Number = .3;
        private var bmpdPlayer:BitmapData;
        private var mtxDraw:Matrix;
        private var projectionTransform:PerspectiveMatrix3D;
        private var m:Matrix3D;
        private var zFar:Number = 5;
        private var program:Program3D;
        
        private var buffers:Vector.<VertexBuffer3D>;
        private var vBufferPos:VertexBuffer3D;
        private var iBuffer:IndexBuffer3D;
        private var btnDir:CheckBox;
        private var sliderSpeed:HSlider;
        
        private var rx:Number = 0;
        private var ry:Number = 0;
        private var offsetY:Number = 0;
        
        private var videoList:ComboBox;
        private var videoURL:String = "SigurRos.flv";
        private var player:VideoPlayer;

        private var stats:Stats;
        
        public function ParticleVideo() {
            W = stage.stageWidth;
            H = stage.stageHeight;
            
            stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, _onContext);
            stage.stage3Ds[0].requestContext3D();
            stage.align = StageAlign.TOP_LEFT;
            stage.scaleMode = StageScaleMode.NO_SCALE;
            
            _initPlayer();
            stats = new Stats(); 
            addChild(stats).y = 365;
            
            Wonderfl.capture_delay(30);
        }
        
        protected function _onContext(e:Event) : void {
            stage.stage3Ds[0].removeEventListener(Event.CONTEXT3D_CREATE, _onContext);
            context = stage.stage3Ds[0].context3D;
            context.configureBackBuffer(W, H, smoothLevel, depthSort);
            _init();
            stage.addEventListener(Event.RESIZE, __onResize);
        }

        
        private function __onResize(e:Event) : void {
            context.configureBackBuffer(stage.stageWidth, stage.stageHeight, 0, false);
            stats.y = stage.stageHeight - 100;
        }        
        
        
        protected function _init() : void {
            _initControl();
            _initShader();
            _initBuffer();
            _initMatrix();
            
            var data:Vector.<Number> = Vector.<Number>([0, -SIZE, 0, 1]);
            context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 10, data, 1);
            
            data = Vector.<Number>([SIZE*.5*ROOT3, SIZE*.5*ROOT3, 0, 1]);
            context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 11, data, 1);
            
            data = Vector.<Number>([-SIZE*.5*ROOT3, SIZE*.5*ROOT3, 0, 1]);
            context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 12, data, 1);
            
            context.setProgram(program);
            context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, m, true);
            
            addEventListener(Event.ENTER_FRAME, _loop);
        }
        
        
        private function _initControl() : void {
            var window:Window = new Window(this, 5, 5, "Controls");
            window.width = 150;
            window.height = 90;
            btnDir = new CheckBox(window.content, 5, 5, "UP / DOWN");
            sliderSpeed = new HSlider(window.content, 5, 20);
            sliderSpeed.value = 50;
            
            videoList = new ComboBox(window.content, 5, 40, "SigurRos.flv", ["SigurRos.flv", "color2_800x450.f4v", "iron.flv"]);
            videoList.selectedIndex = 0;
        }
        
        
        private function _loop(e:Event) : void {
            if(videoURL != videoList.selectedItem.toString() ) {
                videoURL = videoList.selectedItem.toString();
//                trace("Video:" + videoURL);
                player.setVideoURL("http://www.bongiovi.tw/experiments/particleVideo/" + videoURL);
                player.play();
            }
            
            
            context.clear(0, 0, 0, 1);
            //    RESET THE MATRIX
            m = new Matrix3D;
            m.appendScale(2/W, -2/H, 1);
            
            var center:Vector3D = new Vector3D(1, 0, 2); 
            var xx:Number = stage.mouseY/stage.stageHeight * 45;
            var yy:Number = (stage.mouseX/stage.stageWidth - .5)* 90;
            var off:Number = 
                
                rx += ( xx-rx ) * .2;
            ry += ( yy-ry ) * .2;
            offsetY += (stage.mouseY/stage.stageHeight - offsetY) * .2;
            m.appendRotation(rx, Vector3D.X_AXIS, center);
            m.appendRotation(ry, Vector3D.Y_AXIS, center);
            
            m.appendTranslation(-1, 1+offsetY, 0);
            m.append(projectionTransform);
            context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, m, true);
            
            //    CREATE CURRENT FRAME IMAGE
            var vbuffer:VertexBuffer3D = _getCurrentImageBuffer();
            //    PUSHING IN TO BUFFERS
            buffers.unshift(vbuffer);
            if(buffers.length > MAX_BUFFER) buffers.pop();
            
            //    DRAW EACH FRAM
            
            //     UPDATING TIME DATA
            var data:Vector.<Number> = Vector.<Number>([0, 10, 0, 1]);
            var data1:Vector.<Number> = Vector.<Number>([0, 10, 0, 1]);
            var offset:Number = 0;
            
            
            var buf:VertexBuffer3D;
            var f:Function;
            for (var i:int = buffers.length-1; i >=0; i--) {
                offset = 1 - i/MAX_BUFFER;
                offset = Math.sin(offset * Math.PI * .5);
                data = Vector.<Number>([offset, offset, offset, offset]);
                f = btnDir.selected ? Math.sin : Math.cos;
                data1 = Vector.<Number>([f(i/MAX_BUFFER * Math.PI * .5)*sliderSpeed.value/100, 0, 0, 0]);
                context.setProgramConstantsFromVector(Context3DProgramType.FRAGMENT, 0, data, 1);
                context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 5, data1, 1);
                
                context.setVertexBufferAt(0, vBufferPos, 0, Context3DVertexBufferFormat.FLOAT_4);
                context.setVertexBufferAt(1, buffers[i], 0, Context3DVertexBufferFormat.FLOAT_3);
                context.drawTriangles(iBuffer);
            }
            
            context.present();
        }
        
        
        private function _getCurrentImageBuffer() : VertexBuffer3D {
            var vBufferPos:VertexBuffer3D = context.createVertexBuffer(MAX * 3, 3);
            
            bmpdPlayer.draw(player, mtxDraw);
            var colors:Vector.<uint> = bmpdPlayer.getVector(bmpdPlayer.rect);
            var i:int, j:int, posIndex:int, color:uint;;
            var vBufPos:Vector.<Number> = new Vector.<Number>(MAX * 3 * 3);
            var r:Number, g:Number, b:Number;
            var oColor:Object;
            
            for(j=0; j<bmpdPlayer.height; j++) {
                for(i=0; i<bmpdPlayer.width; i++) {
                    color = colors[j*bmpdPlayer.width + i];
                    
                    oColor = getRGB(color);
                    r = oColor.r/255;
                    g = oColor.g/255;
                    b = oColor.b/255;
                    
                    
                    for(var k:int=0; k<3; k++) {
                        vBufPos[posIndex++] = r;
                        vBufPos[posIndex++] = g;
                        vBufPos[posIndex++] = b;
                    }
                }
            }
            
            vBufferPos.uploadFromVector(vBufPos, 0, MAX * 3);
            
            return vBufferPos;
        }
        
        
        private function _initBuffer() : void {
            buffers = new Vector.<VertexBuffer3D>();
            
            
            //    INDICES
            iBuffer = context.createIndexBuffer(MAX * 3);
            var iBuf:Vector.<uint> = new Vector.<uint>(MAX*3);
            var t:int = 0, index:int=0, i:int, j:int, posIndex:int;
            for( i=0; i<MAX; i++) {
                for(t=0; t<INDEX.length; t++) {
                    iBuf[index++] = INDEX[t] + i*3;
                }
            }
            iBuffer.uploadFromVector(iBuf, 0, MAX * 3);
            
            //    VERTICES 
            var vBufPos:Vector.<Number> = new Vector.<Number>(MAX * 3 * 4);
            var tx:Number, ty:Number, tz:Number;
            var count : int = 0, bufferCount:int = 0;
            
            
            for(j=0; j<bmpdPlayer.height; j++) {
                for(i=0; i<bmpdPlayer.width; i++) {
                    tx = i*OFFSET + (W - bmpdPlayer.width*OFFSET) * .5;
                    ty = j*OFFSET + (H - bmpdPlayer.height*OFFSET) * .5;
                    tz = 0;
                    
                    for(var k:int=0; k<3; k++) {
                        vBufPos[posIndex++] = tx;
                        vBufPos[posIndex++] = ty;
                        vBufPos[posIndex++] = tz;
                        vBufPos[posIndex++] = 10+k;
                    }
                }
            }
            vBufferPos = context.createVertexBuffer(MAX * 3, 4);
            vBufferPos.uploadFromVector(vBufPos, 0, MAX * 3);
        }
        
        
        private function _initShader() : void {
            var assembler : AGALMiniAssembler = new AGALMiniAssembler;
            var code:String = "";
            code += "mov vt0, vc[va0.w]\n";
            code += "add vt1, va0, vt0\n";
            code += "mov vt1.w, vt0.w\n";
            code += "mov vt2, va1\n";
            
            code += "mul vt3, vt2, vt2\n";
            code += "add vt3.x, vt3.x, vt3.y\n";
            code += "add vt3.x, vt3.x, vt3.z\n";
            code += "mul vt3.x, vt3.x, vc13.w\n";
            code += "div vt3.x, vt3.x, vc13.x\n";
            code += "mul vt3.x, vt3.x, vc13.y\n";
            code += "add vt3.x, vt3.x, vc13.z\n";
            code += "add vt3.x, vt3.x, vc5.x\n";
            code += "mov vt1.z, vt3.x\n";
            
            code += "m44 op, vt1, vc0\n";
            code += "mov v0, vt2\n";
            var vertextShader : ByteArray = assembler.assemble(Context3DProgramType.VERTEX, code);
            
            code = "mul oc, v0, fc0\n";
            var fragmentShader : ByteArray = assembler.assemble(Context3DProgramType.FRAGMENT, code);
            
            var far:Number = 3;
            var data:Vector.<Number> = Vector.<Number>([3, -far*.3, far, .5]);
            context.setProgramConstantsFromVector(Context3DProgramType.VERTEX, 13, data, 1);
            
            program = context.createProgram();
            program.upload(vertextShader, fragmentShader);
        }    
        
        
        private function _initMatrix() : void {
            projectionTransform = new PerspectiveMatrix3D();
            var aspect:Number = 4/3;
            var zNear:Number = 0.1;
            
            var fov:Number = 45*Math.PI/180;
            projectionTransform.perspectiveFieldOfViewLH(fov, aspect, zNear, zFar);
            
            m = new Matrix3D;
            m.appendScale(4/W, -4/H, 1);
            m.appendTranslation(-2, 2, 0);
            m.append(projectionTransform);
            context.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, m, true);
        }
        
        
        private function _initPlayer() : void {
            player = new VideoPlayer(VIDEO_WIDTH, VIDEO_HEIGHT);
            player.setVideoURL("http://www.bongiovi.tw/experiments/particleVideo/" + videoURL);
            player.play();
            player.setVolume(0);
            
            bmpdPlayer = new BitmapData(VIDEO_WIDTH/SCALE, VIDEO_HEIGHT/SCALE, false, 0);
            mtxDraw = new Matrix;
            mtxDraw.scale(1/SCALE, 1/SCALE);
        }
        
        
        public static function getRGB(pixelValue:uint) : Object {
            var red:uint = pixelValue >> 16 & 0xFF;
            var green:uint = pixelValue >> 8 & 0xFF;
            var blue:uint = pixelValue & 0xFF;
            
            return {r:red, g:green, b:blue};
        }
    }
}

import flash.display.Sprite;
import flash.events.AsyncErrorEvent;
import flash.events.ErrorEvent;
import flash.events.Event;
import flash.events.NetStatusEvent;
import flash.events.SecurityErrorEvent;
import flash.media.SoundTransform;
import flash.media.Video;
import flash.net.NetConnection;
import flash.net.NetStream;


class VideoPlayer extends Sprite {
    private var _nc:NetConnection;
    private var _ns:NetStream;
    private var _video:Video;
    private var _url:String;
    public function VideoPlayer(width:int, height:int) {
        _nc = new NetConnection();
        _nc.addEventListener(NetStatusEvent.NET_STATUS, onStatus);
        _nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onError);
        _nc.connect(null);
        
        _ns = new NetStream(_nc);
        _ns.client = this;
        _ns.addEventListener(NetStatusEvent.NET_STATUS, onStatus);
        _ns.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onError);
        _ns.checkPolicyFile = true;
        
        _video = new Video(width, height);
        _video.smoothing = true;
        _video.attachNetStream(_ns);
        addChild(_video);
    }
    
    
    public function setVideoURL(videoURL:String):void {
        _url = videoURL;
        stop();
    }
    
    
    public function play():void {
        if (!_url)  {
            stop();
            trace("No URL set. Please use the 'setVideoURL' method.");
        } else {
            _ns.play(_url);
        }
    }
    
    
    public function stop():void {
        _ns.close();
        _video.clear();
    }
    
    
    public function setVolume(volume:Number):void {
        var st:SoundTransform = _ns.soundTransform;
        st.volume = volume;
        _ns.soundTransform = st;
    }
    
    private function onError(e:ErrorEvent) : void { trace(e.text);    }
    
    private function onStatus(e:NetStatusEvent) : void {    trace(e.info.code);    }
    
    public function onMetaData(o:Object):void { }
    
    public function onXMPData(info:Object):void { }
}