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

ワイン

Get Adobe Flash player
by zahir 06 Oct 2011
/**
 * Copyright zahir ( http://wonderfl.net/user/zahir )
 * GNU General Public License, v3 ( http://www.gnu.org/licenses/quick-guide-gplv3.html )
 * Downloaded from: http://wonderfl.net/c/4m3w
 */

// forked from zahir's 胸像
package{
    import flash.display.*;
    import flash.events.*;
    import flash.geom.*;
    import flash.net.*;
    import flash.text.TextField;
    import flash.utils.*;
    
    import net.hires.debug.Stats;

    [SWF(width="465", height="465",frameRate="30", backgroundColor="0x666666")]
    public class PolyViewer extends Sprite{
        private var zip:Zip;
        private var imgs:ZIPImages;
        private var l:MQOLoader;
        private var model:MQO;
        private var proj:PerspectiveProjection;
        private var m:Matrix3D;
        private var g:Graphics;
        private var rot:int = 0;
        private var fov:int = 45;
        private var _path:String = "http://zahir.coresv.com/wonderfl/3d/wine/";
        //private var _path:String = "asset/";
        private var s:Shape;
        public function PolyViewer(){
            zip = new Zip( _path + "wine.zip", true );
            zip.addEvent( ProgressEvent.PROGRESS, zipProg);
            zip.addEvent( Zip.READ_COMP, zipComp );
            zip.startLoad();
        }
        private function zipProg( e:ProgressEvent ):void{}
        private function zipComp( e:Event ):void{
            imgs = zip.images;
            imgs.addEvent( ZIPImages.COMP, imgInit);
            imgs.startDecode();
        }
        private function imgInit(e:Event):void{
            imgs.removeEvent( ZIPImages.COMP, imgInit);
            l = new MQOLoader();
            l.addEvent( MQOLoader.PARSE_COMP, modelComp);
            l.load( _path + "wine.mqo", imgs);
        }
        private function modelComp(e:Event):void{
            l.removeEvent( MQOLoader.PARSE_COMP, modelComp);
            model = l.modelData;
            var pp:PerspectiveProjection = new PerspectiveProjection();
            pp.fieldOfView = 60;
            proj = transform.perspectiveProjection;
            proj.fieldOfView = fov;
            m = new Matrix3D();
            var bmp:Bitmap = addChild(new Bitmap(model.texture) ) as Bitmap;
            bmp.width = bmp.height = 465;
            g = (addChild( ( s = new Shape() )) as Shape).graphics;
            s.x = stage.stageWidth >> 1;
            s.y = stage.stageHeight >> 1;
            addChild( new Stats() ).alpha = 0.4;
            stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove );
            stage.addEventListener(MouseEvent.MOUSE_WHEEL, onWheel );
            var t:TextField = new TextField();
            addChild(t).blendMode = BlendMode.INVERT;
            t.autoSize = "left";
            t.text = "Poly :: " + model.polyNum;
            t.x = stage.stageWidth - t.width;
            
            render();
        }
        private function onMove(e:MouseEvent):void{ 
            rot = mouseX * 2;
            render(); 
        }
        private function onWheel(e:MouseEvent):void{
            var d:Number = e.delta;
            if(d < 0) fov -= 1;
            else fov += 1;
            fov = (fov <= 0) ? 1 : (fov >= 180) ? 179 : fov;
            proj.fieldOfView = fov;
            render();
        }
        private function render():void{
            m.identity();
            m.appendRotation( rot, Vector3D.Y_AXIS);
            m.appendTranslation( 0,100, 1000 );
            m.append( proj.toMatrix3D() );
            model.render( g, m);
        }
    }
}
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.net.*;
import flash.utils.*;

import mx.utils.Base64Decoder;
/* いつかやる
class Camera3D{
    public var x:Number, y:Number,z:Number;
    public var rotationX:Number, rotationY:Number, rotationZ:Number;
    public function Camera3D(){}
}
class Scene3D{
}
class Viewport3D{
    private var view:Sprite;
    public function Viewport3D( container:DisplayObjectContainer, scene:Scene3D = null ){
        container.addChild( (view = new Sprite() ) );
        center(0,0);
    }
    public function center( x:Number, y:Number ):void{
        view.x = (view.stage.stageWidth - x) >> 1;
        view.y = (view.stage.stageHeight - y) >> 1;
    }
}//*/
interface IDispatcher{
    function addEvent(type:String, listener:Function):void;
    function removeEvent(type:String, listener:Function):void;
}
interface IDecoder extends IDispatcher{
    function get bitmapData():BitmapData;
    function decode():void;
}
class AbstDispacher implements IDispatcher{
    private var _d:EventDispatcher;
    protected function get d():EventDispatcher{ return _d || ( _d = new EventDispatcher() ); }
    public function addEvent( type:String, listener:Function ):void{ d.addEventListener( type, listener); }
    public function removeEvent( type:String, listener:Function ):void{ d.removeEventListener( type,listener); }
}
class MQOLoader extends AbstDispacher{
    static public const PARSE_COMP:String = "complete_MQO";
    static private const READ_COMP:String = "read_complete_MQO";
    private var s:String;
    private var object_reg:RegExp = /Object \"(.*?)\" \{(.*?}\n)}/sg;
    private var last:int = 0;
    private var mirror:String;
    private var mirror_axis:int;
    private var tempV:Vector.<Vertex>;
    private var indexCounter:uint = 0;
    private var l:URLLoader;
    private var _parsed:Boolean = false;
    private var model:MQO;
    private var material:Material;
    private var texture:ZIPImages;
    private var scale:Number;
    public function MQOLoader(){}
    public function load( modelURL:String, texture:ZIPImages = null ):void{
        this.texture = texture;
        l = new URLLoader();
        l.dataFormat = "binary";
        l.addEventListener(Event.COMPLETE, onComp );
        l.load( new URLRequest( modelURL) );
    }
    public function get modelData():MQO{ return _parsed ? model : null; }
    private function onComp(e:Event):void{
        var b:ByteArray = l.data as ByteArray;
        if(!b)return;
        s = String( b.readMultiByte( b.length, "shift-jis") ).replace(/\r\n/g,"\n");
        s = s.replace(/\t/g,"");
        model = new MQO();
        last = 0;
        tempV = new Vector.<Vertex>();
        scale = Number(/zoom2 (.*?)\n/sg.exec(s)[1]) / 5;
        addEvent( READ_COMP, readComp);
        addEvent( "readMQO_Object", readObjectChunk );
        readObjectChunk();
    }
    private function readComp(e:Event):void{
        removeEvent( "readMQO_Object", readObjectChunk );
        var ind:Vector.<int> = model.indices;
        var len:int = model.vertices.length / 3;
        for(var i:int = 0; i<len; i++) ind[i] = i; // indexの初期化
        var material_reg:RegExp = /Material (.*?) \{\n(.*?)\n}/sg; // マテリアルデータの抽出
        material = new Material();
        if( material_reg.test( s ) ){
            material_reg.lastIndex = 0;s
            var material_data:Array = material_reg.exec( s );
            readMaterial(parseInt(material_data[1]), material_data[2]);
        }model.texture = material.getData();
        d.dispatchEvent( new Event( PARSE_COMP ) );
    }
    private function readMaterial( num:int, data:String ):void{
        var arr:Array = data.split("\n");
        if(num != arr.length)return;
        for(var i:int = 0; i<num; i++){
            var s:String = arr[i] as String;
            var name:String = "";
            var c:Array = (/col\((.*?)\)/s.exec(s)[1] as String).split(" ");
            if(!texture){
                material.addSolidMaterial( ((c[3] * 0xFF)<<24 | (c[0]*0xFF)<<16 | (c[1]*0xFF)<<8 | c[2]*0xFF) );
                return;
            }if(/tex/s.test(s)){
                name = (/tex\(\"(.*?)\"\)/s).exec( s )[1];
                name = name.match( /[^\\]*$/ )[0];
                if( /aplane/s.test(s) ){
                    var a_name:String = (/aplane\(\"(.*?)\"\)/s).exec( s )[1];
                    a_name = a_name.match( /[^\\]*$/ )[0];
                    material.addImageMaterial( texture.getBitmapDataByName( name), texture.getBitmapDataByName( a_name));
                }else material.addImageMaterial( texture.getBitmapDataByName( name) );
            }else{
                material.addSolidMaterial( ((c[3]*0xFF)<<24 | (c[0]*0xFF)<<16 | (c[1]*0xFF)<<8 | c[2]*0xFF) );
            }    
        }
    }
    private function readObjectChunk( e:Event = null ):void{
        tempV.length = 0;
        if( object_reg.test( s ) ){
            object_reg.lastIndex = last;
            
            var obj_data:Array = object_reg.exec( s );
            var str:String = obj_data[2];
            last = object_reg.lastIndex;
            
            if( /mirror (\d)/g.test( str ) ){
                mirror = /mirror (\d)/s.exec( str )[1];
                mirror_axis = parseInt(/mirror_axis (\d)/s.exec( str )[1]);
            }else mirror = "";
            
            var vertex:Array = (/vertex (.*?) \{\n(.*?)\n}/sg).exec( str );
            var face:Array = (/face (.*?) \{\n(.*?)\n}/sg).exec( str );
            
            if(!vertex || !face){
                d.dispatchEvent( new Event( "readMQO_Object" ) );
                return;
            }
            parseVertex( parseInt(vertex[1]), vertex[2] );
            parseFace( parseInt(face[1]), face[2] );
        }else{
            _parsed = true;
            d.dispatchEvent( new Event( READ_COMP ) );
            return;        
        }
        d.dispatchEvent( new Event( "readMQO_Object" ) );
    }
    private function parseVertex( num:uint, chunk:String ):void{
        var arr:Array = chunk.split("\n");
        for(var i:int = 0; i< num; i++){
            var v:Array = (arr[i] as String).split(" ");
            var x:Number = parseFloat( v[0] ) * scale;
            var y:Number = -parseFloat( v[1] ) * scale;
            var z:Number = -parseFloat( v[2] ) * scale;
            tempV[i] = new Vertex(x,y,z);
        }
    }
    private function parseFace( num:int, chunk:String ):void{
        var v:Vector.<Number> = model.vertices;
        var uv:Vector.<Number> = model.uvts;
        var f:Array = model.faces;
        var arr:Array = chunk.split("\n");
        for(var i:int = 0; i<num; i++){
            var s:String = arr[i] as String;
            var vs:Array = (/V\((.*?)\)/sg.exec(s)[1] as String).split(" ");
            var uvs:Array;
            var m_num:int = 0;
            if( /M/sg.test( s ) ){
                m_num = parseInt( /M\((.*?)\)/sg.exec(s)[1] );
                m_num = (m_num < 0) ? -1 : m_num;
            }if( /UV/sg.test(s) ){
                uvs = (/UV\((.*?)\)/sg.exec(s)[1] as String).split(" ");
            }else uvs = [];
            
            if(!vs) return;
            var a:Vertex, b:Vertex, c:Vertex, d:Vertex;
            var uvA:UV, uvB:UV, uvC:UV, uvD:UV;
            var _uv:UV = new UV(0,0);
            if(m_num < 4) _uv.uv( 0.25 * (m_num%4));
            else if(m_num < 8) _uv.uv( 0.25 * (m_num%4), 0.25);
            else if(m_num < 12) _uv.uv( 0.25 * (m_num%4), 0.5);
            else if(m_num < 16) _uv.uv( 0.25 * (m_num%4), 0.75);

            if( vs.length == 3){//*
                c = tempV[ parseInt( vs[0] ) ];
                b = tempV[ parseInt( vs[1] ) ];
                a = tempV[ parseInt( vs[2] ) ];
                push3();
                if(mirror == "1"){
                    a = mirrorVertex(a, mirror_axis);
                    b = mirrorVertex(b, mirror_axis);
                    c = mirrorVertex(c, mirror_axis);
                    push3(true);
                }//*/
            }else if( vs.length == 4){//*
                d = tempV[ parseInt( vs[0] ) ];
                c = tempV[ parseInt( vs[1] ) ];
                b = tempV[ parseInt( vs[2] ) ];
                a = tempV[ parseInt( vs[3] ) ];
                push4();
                if(mirror == "1"){
                    a = mirrorVertex(a, mirror_axis);
                    b = mirrorVertex(b, mirror_axis);
                    c = mirrorVertex(c, mirror_axis);
                    d = mirrorVertex(d, mirror_axis);
                    push4( true );
                }//*/
            }
            function push3(mirror:Boolean = false):void{
                if(!mirror) v.push( c.x, c.y, c.z, b.x, b.y, b.z, a.x, a.y, a.z );
                else  v.push( a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z );
                f.push( new Face() );
                if(uvs.length){
                    uvC = getUV( parseFloat(uvs[0]), parseFloat(uvs[1]), _uv );
                    uvB = getUV( parseFloat(uvs[2]), parseFloat(uvs[3]), _uv );
                    uvA = getUV( parseFloat(uvs[4]), parseFloat(uvs[5]), _uv );
                    if(!mirror) uv.push( uvC.u, uvC.v, 0, uvB.u, uvB.v, 0, uvA.u, uvA.v, 0 );
                    else uv.push( uvA.u, uvA.v, 0, uvB.u, uvB.v, 0, uvC.u, uvC.v, 0 );
                }else uv.push( 0,0,0, 0,0,0, 0,0,0 );
            }
            function push4( mirror:Boolean = false ):void{
                if(!mirror)
                    v.push(    c.x, c.y, c.z, b.x, b.y, b.z, a.x, a.y, a.z,
                            a.x, a.y, a.z, d.x, d.y, d.z, c.x, c.y, c.z );
                else
                    v.push(    a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z,
                            c.x, c.y, c.z, d.x, d.y, d.z, a.x, a.y, a.z );
                f.push( new Face(), new Face() );
                if(uvs.length){
                    uvD = getUV( parseFloat(uvs[0]), parseFloat(uvs[1]), _uv );
                    uvC = getUV( parseFloat(uvs[2]), parseFloat(uvs[3]), _uv );
                    uvB = getUV( parseFloat(uvs[4]), parseFloat(uvs[5]), _uv );
                    uvA = getUV( parseFloat(uvs[6]), parseFloat(uvs[7]), _uv );
                    if(!mirror)
                        uv.push(    uvC.u, uvC.v, 0, uvB.u, uvB.v, 0, uvA.u, uvA.v, 0,
                                    uvA.u, uvA.v, 0, uvD.u, uvD.v, 0, uvC.u, uvC.v, 0 );
                    else
                        uv.push(    uvA.u, uvA.v, 0, uvB.u, uvB.v, 0, uvC.u, uvC.v, 0,
                                    uvC.u, uvC.v, 0, uvD.u, uvD.v, 0, uvA.u, uvA.v, 0 );
                }else uv.push( 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0, 0,0,0 );
            }
        }
    }
    private function getUV(u:Number, v:Number, offset:UV):UV{
        return new UV( (u/4) + offset.u, (v/4) + offset.v );
    }
    private function mirrorVertex(v:Vertex, axis:int):Vertex{
        return new Vertex( ((axis & 1) != 0) ? -v.x : v.x, ((axis & 2) != 0) ? -v.y : v.y, ((axis & 4) != 0) ? -v.z : v.z);
    }
}
class Material{
    static private const p:Point = new Point(0,0);
    private var bd:BitmapData;
    private var solid:BitmapData;
    private var m:Matrix;
    private var count:int;
    public function Material(){
        bd = new BitmapData(2048, 2048, true, 0);
        solid = new BitmapData(512,512, true, 0);
        m = new Matrix();
    }
    public function getData():BitmapData{ return bd.clone(); }
    public function addImageMaterial( src:BitmapData, alpha:BitmapData = null ):void{
        if(count >= 16) return;
        draw( src, alpha );
    }
    public function addSolidMaterial(ARGB:uint = 0xFF000000):void{
        if(count >= 16) return;
        solid.lock();
        solid.fillRect( solid.rect, ARGB );
        solid.unlock();
        draw( solid );
    }
    private function draw( src:BitmapData, alpha:BitmapData = null):void{
        var _src:BitmapData;
        if(alpha){
            alpha.applyFilter( alpha, src.rect, p, new G2AFilter() );
            src.copyPixels( src, src.rect, p, alpha, p); 
        }if( src.width != src.height ){
            
            var tx:Number = 1, ty:Number = 1;
            if(src.width > src.height){
                ty = src.width / src.height;
                _src = new BitmapData(src.width,src.width, true, 0);
            }else{
                tx = src.height / src.width;
                _src = new BitmapData(src.height,src.height, true, 0);
            }m.identity(); m.scale(tx,ty);
            _src.lock();
            _src.draw(src, m);
            _src.unlock();
            $( _src.clone() );
            _src.dispose();
        }else $( src );
    }
    private function $( src:BitmapData ):void{
        var scale:Number = 1;
        if( src.width > src.height) scale = 512 / src.width;
        else scale = 512 / src.height;
        m.identity();
        m.scale(scale, scale);
        if(count < 4) m.translate( (count%4) * 512, 0);
        else if(count < 8) m.translate( (count%4) * 512, 512);
        else if(count < 12) m.translate( (count%4) * 512, 1024);
        else if(count < 16) m.translate( (count%4) * 512, 1536);
        else return;
        bd.lock();
        bd.draw( src, m );
        bd.unlock();
        count++;
    }
}
class MQO{
    public var vertices:Vector.<Number>;
    public var indices:Vector.<int>;
    public var uvts:Vector.<Number>;
    public var faces:Array;
    private var pv:Vector.<Number>;
    private var sortedIndices:Vector.<int>;
    private var bd:BitmapData;
    public function MQO(){
        vertices = new Vector.<Number>();
        indices = new Vector.<int>();
        uvts = new Vector.<Number>();
        faces = [];
        pv = new Vector.<Number>();
        sortedIndices = new Vector.<int>();
        bd = new BitmapData(256,256);
        for(var b:int = 0; b<=256; b++) for(var g:int = 0; g<=256; g++) bd.setPixel( g,b, (0x0000 | (g<<8) | b) );
    }
    public function get polyNum():int{ return faces.length; }
    public function get texture():BitmapData{ return bd.clone(); }
    public function set texture( value:BitmapData ):void{ bd = value.clone(); }
    public function render( graphics:Graphics, matrix:Matrix3D ):void{
        Utils3D.projectVectors( matrix, vertices, pv, uvts );
        var face:Face;
        var inc:int = 0, len:int = indices.length;
        for (var i:int = 0; i<len; i+=3){
            face = faces[inc++] as Face;
            face.x = indices[i];
            face.y = indices[ i + 1 ];
            face.z = indices[ i + 2 ];
            var i3:int = i*3;
            face.w = uvts[ i3 + 2 ] + uvts[ i3 + 5 ] + uvts[ i3 + 8 ];
        }
        inc = 0;
        faces.sortOn("w", Array.NUMERIC);
        for each (face in faces){
            sortedIndices[inc++] = face.x;
            sortedIndices[inc++] = face.y;
            sortedIndices[inc++] = face.z;
        }
        graphics.clear();
        graphics.beginBitmapFill( bd, null, true, true );
        graphics.drawTriangles( pv, sortedIndices, uvts, "negative");
        graphics.endFill();
    }
}
class Zip extends AbstDispacher{
    static public const LOAD_COMP:String = "zip_load_complete";
    static public const READ:String = "zip_read";
    static public const READ_COMP:String = "zip_read_complete";
    static private const SIGNATURE:uint = 0x04034b50;
    private var l:URLLoader;
    private var url:String;
    private var autoStart:Boolean = false;
    private var _loaded:Boolean = false;
    private var _readed:Boolean = false;
    private var _check:Boolean = false;    
    private var _read:Event;
    private var _data:ByteArray;
    private var imgs:ZIPImages;
    public function Zip( url:String , autoStart:Boolean = false){
        if( check(url) ){
            _check = true;
            this.url = url;
            this.autoStart = autoStart;
            _read = new Event( READ );
        }
    }
    public function startLoad():void{
        if(_loaded) return;
        if(!_check) return;
        l = new URLLoader();
        l.dataFormat = "binary";
        l.addEventListener( Event.COMPLETE , complete );
        l.addEventListener(ProgressEvent.PROGRESS, onProg);
        l.load( new URLRequest(url) );
    }
    private function onProg( e:ProgressEvent ):void{ d.dispatchEvent(e); }
    private function complete( e:Event ):void{
        l.removeEventListener( ProgressEvent.PROGRESS, onProg );
        l.removeEventListener( Event.COMPLETE , complete );
        d.dispatchEvent( new Event( LOAD_COMP ) );
        addEvent(READ, read);
        _loaded = true;
        _data = l.data;
        _data.endian = "littleEndian";
        imgs = new ZIPImages();
        if(autoStart) read();
    }
    public function startReading():void{ if(loaded) read(); }
    private function read( e:Event = null ):void{
        if( _data.bytesAvailable ){
            if( _data.readInt() !== SIGNATURE ){
                removeEvent(READ, read);
                _data.clear();
                _readed = true;
                d.dispatchEvent( new Event( READ_COMP ) );
                return;
            }
            _data.position += 4;
            var compression:int = _data.readUnsignedShort();
            _data.position += 8;
            var compSize:uint = _data.readUnsignedInt();
            var uncompSize:uint = _data.readUnsignedInt();
            var fileNameLength:uint = _data.readUnsignedShort();
            var exFieldLength:uint = _data.readUnsignedShort();
            var fileName:String = _data.readUTFBytes( fileNameLength );
            _data.readUTFBytes( exFieldLength );
            if(compSize){
                var b:ByteArray = new ByteArray();
                _data.readBytes( b, 0, compSize );
                if(compression == 8) b.inflate();
            }
            var reg:RegExp = /\.jpg$|\.jpeg$|\.png$|\.tga$|\.bmp$/sig;
            if( reg.test( fileName) ) imgs.push( new ZIPImage( b, fileName) ); // image以外を無視
            d.dispatchEvent( _read );
        }else{
            removeEvent(READ, read);
            _readed = true;
            d.dispatchEvent( new Event( READ_COMP ) );
        }
    }
    private function check(url:String):Boolean { return (/\.zip$/sig.test( url )) ? true : false; }
    public function get images():ZIPImages{ return imgs; }
    public function get loaded():Boolean{ return _loaded ? true : false; }
}
class ZIPImages extends AbstDispacher{
    static public const COMP:String = "zip_image_complete";
    private var imgs:Vector.<ZIPImage>;
    private var count:int = 1;
    private var imgInit:Boolean = false;
    public function ZIPImages():void{ imgs = new Vector.<ZIPImage>(); }
    public function push( img:ZIPImage ):void{
        img.container = this;
        imgs.push( img );
    }
    public function startDecode():void{ for(var i:int = 0; i<imgs.length; i++) imgs[i].start(); }
    public function getBitmapDataByName( name:String ):BitmapData{
        for(var i:int = 0, len:int = imgs.length; i<len; i++){
            var img:ZIPImage = imgs[i] as ZIPImage;
            if(new RegExp(name).test(img.name)) return img.bitmapData;
        }
        return new BitmapData(1,1);
    }
    public function getBitmapData( num:int ):BitmapData{ return imgs[num].bitmapData; }
    public function setComp():void{
        if( (count++) >= imgs.length){
            imgInit = true;
            d.dispatchEvent(new Event(COMP));
        }
    }
}
class ZIPImage{
    private var l:Loader;
    private var d:IDecoder;
    private var _name:String;
    private var bd:BitmapData;
    private var decoded:Boolean = false;
    public var container:ZIPImages;
    public function ZIPImage( data:ByteArray, name:String){
        this._name = name.match(/[^\/]*$/)[0];
        if(/\.tga$/i.test(name)) d = new TGA( data );
        else if(/\.bmp$/i.test(name)) d = new BMP( data );
        else d = new BuiltInDecoder( data );
        d.addEvent( Decoder.COMP, onDecodeComp);
    }
    public function start():void{if(decoded) return; d.decode(); }
    private function onDecodeComp(e:Event):void{
        d.removeEvent( Decoder.COMP, onDecodeComp);
        if(container) container.setComp();
        decoded = true;
        bd = d.bitmapData;
        d = null;
    }
    public function get name():String{ return _name; }
    public function get bitmapData():BitmapData{ return bd ? bd : new BitmapData(1,1); }
    public function dispose():void{ if(bd) bd.dispose(); }
}
class Decoder extends AbstDispacher implements IDecoder{
    public static const COMP:String = "decode_comp";
    protected var width:Number, height:Number;
    protected var data:ByteArray;
    protected var bd:BitmapData;
    private var decoded:Boolean = false;
    public function Decoder( data:ByteArray ){ this.data = data; }
    public function decode():void{}
    public function get bitmapData():BitmapData{ return decoded ? bd.clone(): new BitmapData(1,1); }
    protected function decodeComp():void{
        decoded = true;
        d.dispatchEvent( new Event(COMP) );
    }
}
class BuiltInDecoder extends Decoder{
    private var l:Loader;
    public function BuiltInDecoder( data:ByteArray ){
        super(data);
        (l = new Loader()).contentLoaderInfo.addEventListener(Event.COMPLETE, comp);
    }
    override public function decode():void{ l.loadBytes( data ); }
    private function comp(e:Event):void{
        l.contentLoaderInfo.removeEventListener(Event.COMPLETE, comp);
        bd = (l.content as Bitmap).bitmapData.clone();
        l = null;
        decodeComp();
    }
}
class TGA extends Decoder{
    private const TYPE_NONE:uint = 0x00;
    private const TYPE_INDEX_COLOR:uint = 0x01;
    private const TYPE_FULL_COLOR:uint = 0x02;
    private const TYPE_RLE_BIT:uint = 0x08;
    private const DIR_RIGHT_UP:int = 0;
    private const DIR_LEFT_UP:int = 1;
    private const DIR_RIGHT_DOWN:int = 2;
    private const DIR_LEFT_DOWN:int = 3;
    private var _idLength:int;
    private var _colorMapType:int;
    private var _imageType:int;
    private var _colorMapIndex:int;
    private var _colorMapLength:int;
    private var _colorMapSize:int;
    private var _originX:int;
    private var _originY:int;
    private var _bitDepth:int;
    private var _descriptor:int;
    public function get pixelDirection():int { return (_descriptor >> 4) & 3; }
    public function TGA( data:ByteArray ){ super(data); }
    override public function decode():void{
        data.endian = "littleEndian";
        _idLength = data.readByte();
        _colorMapType = data.readByte();
        _imageType = data.readByte();
        _colorMapIndex = data.readShort();
        _colorMapLength = data.readShort();
        _colorMapSize = data.readByte()
        _originX = data.readShort();
        _originY = data.readShort();
        width = data.readShort();
        height = data.readShort();
        _bitDepth = data.readByte();
        _descriptor = data.readByte();
        bd = new BitmapData(width, height);
        if ((_imageType & TYPE_FULL_COLOR) == 0|| (_imageType & TYPE_RLE_BIT) != 0) throw new Error("Unsupported tga format.");
        bd.lock();
        if(_bitDepth == 32) loadBitmap32(data);
        if(_bitDepth == 24) loadBitmap24(data);
        bd.unlock();
        decodeComp();
    }
    private function loadBitmap32(bytes:ByteArray):void{
        var x:int, y:int;
        switch (pixelDirection){
            case DIR_RIGHT_UP:
                for (y = bd.height - 1; y >= 0; --y){
                    for (x = 0; x < bd.width; ++x) bd.setPixel32(x, y, bytes.readUnsignedInt());
                } break;
            case DIR_LEFT_UP:
                for (y = bd.height - 1; y >= 0; --y){
                    for (x = bd.width - 1; x >= 0; --x) bd.setPixel32(x, y, bytes.readUnsignedInt());
                } break;
            case DIR_RIGHT_DOWN:
                for (y = 0; y < bd.height; ++y){
                    for (x = 0; x < bd.width; ++x) bd.setPixel32(x, y, bytes.readUnsignedInt());
                } break;
            case DIR_LEFT_DOWN:
                for (y = 0; y < bd.height; ++y){
                    for (x = bd.width - 1; x >= 0; --x) bd.setPixel32(x, y, bytes.readUnsignedInt());
                } break;
        }
    }
    private function loadBitmap24(bytes:ByteArray):void{
        var x:int, y:int;
        var r:uint, g:uint, b:uint;
        switch (pixelDirection){
            case DIR_RIGHT_UP:
                for (y = bd.height - 1; y >= 0; --y){
                    for (x = 0; x < bd.width; ++x) setPixel();
                }
                break;
            case DIR_LEFT_UP:
                for (y = bd.height - 1; y >= 0; --y){
                    for (x = bd.width - 1; x >= 0; --x) setPixel();
                }
                break;
            case DIR_RIGHT_DOWN:
                for (y = 0; y < bd.height; ++y){
                    for (x = 0; x < bd.width; ++x) setPixel();
                }
                break;
            case DIR_LEFT_DOWN:
                for (y = 0; y < bd.height; ++y){
                    for (x = bd.width - 1; x >= 0; --x) setPixel();
                }
                break;
        }
        function setPixel():void{
            b = bytes.readUnsignedByte();
            g = bytes.readUnsignedByte();
            r = bytes.readUnsignedByte();
            bd.setPixel(x, y, (r << 16) | (g << 8) | b);
        }
    }
}
class BMP extends Decoder{
    private var pos:uint;
    private var b:ByteArray;
    private var fileSize:uint = 0;
    private var offset:uint = 0;
    private var infoHeaderSize:int = 0;
    private var planes:int = 1;
    private var bitCount:uint = 1;
    private var compression:int = 0;
    private var imageSize:int = 0;
    private var usedColor:uint = 0;
    private var palleteIndex:uint = 0;
    private var rMask:uint = 0, gMask:uint = 0, bMask:uint = 0;
    private var rPos:uint = 0,gPos:uint = 0, bPos:uint = 0;
    private var rMax:uint = 0, gMax:uint = 0, bMax:uint = 0;
    private var pallete:Array;
    public function BMP( data:ByteArray ){ super(data); }
    private function readFileHeader():Boolean{
        if( b.readUTFBytes( 2 ) != "BM" ) return false;
        fileSize =  b.readUnsignedInt();
        b.position += 4;
        offset = b.readUnsignedInt();
        return true;
    }
    private function readInfoHeader():void{
        infoHeaderSize = b.readUnsignedInt();
        if( infoHeaderSize == 40){
            width = b.readUnsignedInt();
            height = b.readUnsignedInt();
            b.position += 2;
            bitCount = b.readUnsignedShort();
            compression = b.readUnsignedInt();
            imageSize = b.readUnsignedInt();
            b.position += 8;
            usedColor = b.readUnsignedInt();
            palleteIndex = b.readUnsignedInt();
        }else if( infoHeaderSize == 12){
            width = b.readUnsignedShort();
            height = b.readUnsignedShort();
            b.position += 2;
            bitCount = b.readUnsignedShort();
        }
    }
    override public function decode():void{
        b = data;
        b.endian = "littleEndian";
        b.position = 0;
        if( !readFileHeader() ) return;
        readInfoHeader();
        bd = new BitmapData( width, height, true, 0xFF333333);
        if( bitCount > 16){
            readBitFieald();
            checkMask();
        }bd.lock();
        if( bitCount <= 16) bd.fillRect(bd.rect,0xFFFFFF); // 16bit以下は行数の都合上無視
        else if( bitCount == 24) dec24bit();
        else if( bitCount == 32) dec32bit();
        bd.unlock();
        decodeComp();
    }
    private function dec24bit():void{
        var bf:ByteArray = new ByteArray();
        var len:int = width * 3;
        if( len % 4 > 0) len = ( (len/4|0) + 1 ) * 4;
        for( var y:int = height - 1; y >= 0; y--){
            bf.length = 0; b.readBytes( bf, 0, len );
            for( var x:int = 0; x<width; x++){
                var c:uint = (bf.readUnsignedByte() | ( bf.readUnsignedByte() << 8 ) | ( bf.readUnsignedByte() << 16)) 
                bd.setPixel(x,y,c);
            }
        }
    }
    private function dec32bit():void{
        for(var y:int = height - 1; y >= 0; y--){
            for(var x:int = 0; x<width; x++){
                var c:uint = b.readUnsignedInt();
                c = ( ( ( c & rMask ) >> rPos )*0xff/rMax << 16 ) + ( ( ( c & gMask ) >> gPos )*0xff/gMax << 8 ) + ( ( ( c & bMask ) >> bPos )*0xff/bMax << 0 )
                bd.setPixel(x,y,c);
            }
        }
    }
    private function readBitFieald():void{
        if( compression == 0){
            if( bitCount == 16){
                rMask = 0x00007c00; gMask = 0x000003e0; bMask = 0x0000001f;
            }else{
                rMask = 0x00ff0000; gMask = 0x0000ff00; bMask = 0x000000ff;
            }
        }else if( (compression == 3) && (infoHeaderSize < 52) ){
            rMask = b.readUnsignedInt(); gMask = b.readUnsignedInt(); bMask = b.readUnsignedInt();
        }
    }
    private function checkMask():void{
        if ( ( rMask & gMask ) | ( gMask & bMask ) | (bMask & rMask ) ) throw new Error();
        while( (( rMask >> rPos ) & 0x00000001) == 0 ) rPos++;
        while( (( gMask >> gPos ) & 0x00000001) == 0 ) gPos++;
        while( (( bMask >> bPos ) & 0x00000001) == 0 ) bPos++;
        rMax = rMask >> rPos; gMax = gMask >> gPos; bMax = bMask >> bPos;
    }
}
class G2AFilter extends ShaderFilter{
    static private var code:ByteArray;
    {    static private var dec:Base64Decoder = new Base64Decoder() ;
        dec.decode(
            "pQEAAACkCQBHMkFGaWx0ZXKgDG5hbWVzcGFjZQBqcC56YWhpcgCgDHZlbmRvcgB6YWhpcgCgCHZl" +
            "cnNpb24AAQCgDGRlc2NyaXB0aW9uAGdyYXlTY2FsZSAtPiBhbHBoYQChAQIAAAxfT3V0Q29vcmQA" +
            "owAEc3JjAKECBAEAD2RzdAAwAgDxAAAQAB0BAPMCABsAHQEAEAEAAAA=" );
        code = dec.toByteArray(); dec = null;
    }public function G2AFilter(){ super( new Shader( code) ) }
}
class Vertex{
    public var x:Number, y:Number, z:Number;
    public function Vertex( x:Number = 0, y:Number = 0, z:Number = 0){ this.x = x; this.y = y; this.z = z; }
}
class UV{
    public var u:Number, v:Number;
    public function UV( u:Number, v:Number){ uv(u,v) }
    public function uv( u:Number = 0, v:Number = 0):void{ this.u = u; this.v = v; }
}
class Face{
    public var x:Number, y:Number, z:Number, w:Number;
    public function Face( x:Number = 0, y:Number = 0, z:Number = 0, w:Number = 0){
        this.x = x; this.y = y; this.z = z; this.w = w;
    }
}