重い地球

by umhr forked from 多面体 (diff: 466)
地球儀
zSortやライティングをちゃんとやると、
やっぱ重くなる。

♥0 | Line 213 | Modified 2015-07-15 16:25:11 | MIT License
play

ActionScript3 source code

/**
 * Copyright umhr ( http://wonderfl.net/user/umhr )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/cqgV
 */

/*

地球儀
zSortやライティングをちゃんとやると、
やっぱ重くなる。

*/
package {
    import flash.display.Sprite;
    import flash.display.BitmapData;
    import flash.display.Graphics;
    import flash.geom.Vector3D;
    import flash.geom.Matrix3D;
    import flash.geom.Point;
    import flash.geom.PerspectiveProjection;
    import flash.events.Event;
    import net.hires.debug.Stats;
    [SWF(backgroundColor="0x000000")]
    public class Main extends Sprite {
        private var spec_data:BitmapData = new BitmapData(100,50);
        private var _sp:Sprite=new Sprite;
        private var vectors_vec:Vector.<Vector.<Number>>;
        private var polyInt:int;
        private var scale:Number;
        private var loadFiles_array:Array;
        private var color_array:Vector.<int> = new Vector.<int>((100-1)*(50-1));
        private var spec_array:Array = new Array();
        private var _stageWidth:int = stage.stageWidth;
        private var _stageHeight:int = stage.stageHeight;
        private var MultiLoader:MultiLoaderClass = new MultiLoaderClass("http://mztm.jp/crossdomain.xml");
        
        private var baseBmpd:BitmapData = new BitmapData(230,465,false,0x33);
        
        public function Main():void {
            loadFiles_array = MultiLoader.setLoad(["http://mztm.jp/wonderfl/earthmap100.png","http://mztm.jp/wonderfl/earthbump100.png"],onImgComp);
            
            graphics.beginFill(0x000000);
            graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
            graphics.endFill();
            
            var pp:PerspectiveProjection=this.transform.perspectiveProjection;
            pp.projectionCenter=new Point(stage.stageWidth/4,stage.stageHeight/4);
            this.transform.perspectiveProjection=pp;
            _sp.z=_sp.z;
            _sp.x=stage.stageWidth/4;
            _sp.y=stage.stageHeight/4;
            addChild(_sp);
            addChild(new Stats());
        }
        private function onImgComp():void{
            var bmp_data:BitmapData = new BitmapData(100,50)
            bmp_data.draw(loadFiles_array[0]);
            spec_data.draw(loadFiles_array[1]);
            getPixels(bmp_data);
            vectors_vec = toSpherical(100,50);
            scale = 1.1;
            addEventListener(Event.ENTER_FRAME,ENTER_FRAME);
        }
    
        private function getPixels(_bmpd:BitmapData):void{
            var bmpw:int = _bmpd.width;
            var bmph:int = _bmpd.height;
            for (var h:uint = 0; h < bmph-1; h++) {
                for (var w:uint = 0; w < bmpw-1; w++) {
                    color_array[w+(bmpw-1)*h] = _bmpd.getPixel(w,h);
                }
            }
        }
        private function toSpherical(_bmpw:uint,_bmph:uint):Vector.<Vector.<Number>>{
            var _array:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();
            var temp_array:Vector.<Vector.<Number>> = new Vector.<Vector.<Number>>();
            for (var h:uint = 0; h < _bmph; h++) {
                for (var w:uint = 0; w < _bmpw; w++) {
                    var nnx:Number = Math.PI*(2*(w-(_bmpw-1)/2)/(_bmpw-1));
                    var nny:Number = -Math.PI*((h-(_bmph-1)/2)/(_bmph-1));
                    var _scale:Number = 1+(spec_data.getPixel(w,h)/0xFFFFFF)/15;
                    var nx:Number = Math.cos(nny)*Math.cos(nnx)*_scale;
                    var ny:Number = Math.cos(nny)*Math.sin(nnx)*_scale;
                    var nz:Number = Math.sin(nny)*_scale;                    
                    nx = Math.abs(nx) < 0.001 ? 0: nx;
                    ny = Math.abs(ny) < 0.001 ? 0: ny;
                    var _a:Vector.<Number> = new Vector.<Number>(3,true);
                    _a = Vector.<Number>([nx,ny,nz]);
                    temp_array.push(_a);
                }
            }
            for (h = 0; h < _bmph-1; h++) {
                for (w = 0; w < _bmpw-1; w++) {
                    _array.push(temp_array[h*_bmpw+w].concat(temp_array[h*_bmpw+w+1],temp_array[(h+1)*_bmpw+w+1],temp_array[(h+1)*_bmpw+w]));
                }
            }
            return _array;
        }
        
        private var _num:Number=0;
        private function ENTER_FRAME(e:Event=null):void {
            _num+=0.01;
            _sp.graphics.clear();
            var vv:Vector.<Vector3D>=new Vector.<Vector3D>(3);
            vv[0]=new Vector3D(0,0,0);//平行移動、
            vv[1]=new Vector3D(_num/20+90,_num,0);//回転、
            vv[2]=new Vector3D(180/scale,180/scale,180/scale);//拡大 / 縮小
            var matrix1:Matrix3D=new Matrix3D();
            matrix1.recompose(vv);
            var vectors_vec_length:int = vectors_vec.length;
            var vout_vec:Vector.<Vector.<Number>>=new Vector.<Vector.<Number>>(vectors_vec_length);
            for (var i:int=0; i<vectors_vec_length; i++) {
                vout_vec[i] = new Vector.<Number>(3);
                matrix1.transformVectors(vectors_vec[i],vout_vec[i]);
            }
            render(vout_vec);
        }
        
        private function render(_pozz:Vector.<Vector.<Number>>):void{
            var _len:int=_pozz.length;
            var _z_vector:Array=new Array();
            for (var i:int=0; i<_len; i++) {
                var i_len:int = _pozz[i].length/3;
                _z_vector[i] = 0;
                for (var j:int=0; j<i_len; j++) {
                    _z_vector[i] += _pozz[i][j*3+2];
                }
            }
            _z_vector = _z_vector.sort(Array.NUMERIC|Array.RETURNINDEXEDARRAY|Array.DESCENDING);
            var _mouseX:Number = stage.mouseX-_stageWidth/2;
            var _mouseY:Number = stage.mouseY-_stageHeight/2;
            for (i=0; i<_len; i++) {
                drawLine(_pozz[_z_vector[i]],color_array[_z_vector[i]],_mouseX,_mouseY);
            }
        }
        private function drawLine(poz:Vector.<Number>,_color:int,_mouseX:Number,_mouseY:Number):void{
            //隠面消去
            var _vec:Vector3D = new Vector3D(poz[0]-poz[3],poz[1]-poz[4],poz[2]-poz[5]).crossProduct(new Vector3D(poz[0]-poz[6],poz[1]-poz[7],poz[2]-poz[8]));
            if(_vec.length == 0){
                _vec = new Vector3D(poz[0]-poz[3],poz[1]-poz[4],poz[2]-poz[5]).crossProduct(new Vector3D(poz[0]-poz[9],poz[1]-poz[10],poz[2]-poz[11]));
            }
            if(_vec.z > 0 ){
                return;
            }
            //フラットシェーディング
            _mouseX = Math.abs(_mouseX)>300?300*_mouseX/Math.abs(_mouseX):_mouseX;
            _mouseY = Math.abs(_mouseY)>300?300*_mouseY/Math.abs(_mouseY):_mouseY;
            var _ang:Number = Vector3D.angleBetween(_vec,new Vector3D(_mouseX,_mouseY,-500));
            //_sp.graphics.lineStyle(0,0xFF0000);
            _sp.graphics.beginFill (rgbBrightness(_color,(1-_ang/2)), 1);
            var _len:int=poz.length;
            var ps:Point=_sp.local3DToGlobal(new Vector3D(poz[_len-3],poz[_len-2],poz[_len-1]));
            _sp.graphics.moveTo(ps.x,ps.y);
            
            for (var i:int=0; i<_len/3; i++) {
                ps=_sp.local3DToGlobal(new Vector3D(poz[i*3],poz[i*3+1],poz[i*3+2]));
                _sp.graphics.lineTo(ps.x,ps.y);
            }
            _sp.graphics.endFill();
        }
        //
        /*
        色の明度を相対的に変える関数。
        rgb値と割合を与えて、結果を返す。
        rgbは、0xffffff段階の値。
        ratioが0の時に0x000000に、1の時にそのまま、2の時には0xffffffになる。
        相対的に、ちょっと暗くしたい時には、ratioを0.8に、
        ちょっと明るくしたい時にはratioを1.2などに設定する。
        */
        public function rgbBrightness(rgb:int,ratio:Number = 1):int{
            if(ratio < 0 || 2 < ratio){ratio = 1}
            var _r:int = rgb >> 16;//16bit右にずらす。
            var _g:int = rgb >> 8 & 0xff;//8bit右にずらして、下位8bitのみを取り出す。
            var _b:int = rgb & 0xff;//下位8bitのみを取り出す。
            if(ratio <= 1){
                _r *= ratio;
                _g *= ratio;
                _b *= ratio;
            }else{
                _r = (255 - _r)*(ratio-1)+_r;
                _g = (255 - _g)*(ratio-1)+_g;
                _b = (255 - _b)*(ratio-1)+_b;
            }
            return _r<<16 | _g<<8 | _b;
        }
    }
}


class MultiLoaderClass{
    import flash.system.Security;
    import flash.net.URLRequest;
    import flash.net.URLLoader;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.display.Loader;
    //import flash.display.LoaderInfo;
    
    private var onComplete:Function = function():void{};
    private var loadNum:int;
    private var loadCompNum:int;
    
    public function MultiLoaderClass(_str:String = null){
        if(_str != null){
            Security.loadPolicyFile(_str);
        }
    }
    
    public function setLoad(__item_array:Array,_onComp:Function = null):Array{
        loadCompNum = loadNum = 0;
        onComplete = _onComp;
        var _array:Array = new Array();
        var _length:int = __item_array.length;
        for (var i:int = 0; i < _length; i++) {
            if(__item_array[i] == null){continue};
            var _extension:String = __item_array[i].substr(-4,4).toLowerCase();//拡張子を取り出す。
            if(_extension == ".xml"){
                loadNum ++;
                _array[i] = fnURLLoader(__item_array[i]);
            }else if(_extension == ".jpg" || _extension == ".png"){
                loadNum ++;
                _array[i] = fnLoader(__item_array[i]);
            }else{
                //_array[i] = null;
            }
        }
        return _array;
    }
    private function fnURLLoader(__url:String):URLLoader{
        var _loader : URLLoader = new URLLoader();
        _loader.load(new URLRequest(__url));
        _loader.addEventListener (Event.COMPLETE,completeHandler);
        _loader.addEventListener (IOErrorEvent.IO_ERROR, ioErrorHandler);
        return _loader;            
    }
    
    private function fnLoader(__url:String):Loader{
        var _loader:Loader = new Loader();
        _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
        _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
        _loader.load(new URLRequest(__url));
        //_loader.name = __url;
        return _loader;
    }
    
    private function completeHandler(event:Event = null):void {
        loadCompNum ++;
        if(loadCompNum == loadNum){
            onComplete();
        }
        //var loaderInfo:LoaderInfo=event.currentTarget as LoaderInfo;
        //var loader:Loader=loaderInfo.loader;
        //addChild(loader);
    }
    
    private function ioErrorHandler(event:IOErrorEvent):void {
        //event.text = "Error #2035: URL が見つかりません。 URL: file:///~~~~~";
        //event.text = "Error #2036: 読み込みが未完了です。 URL: http://~~~~~";
        //から、URLのみを取り出す。
        //trace(String(event.text).substr(String(event.text).indexOf(" URL: ")+6),"*****");
        completeHandler();
    }
}