重い地球
forked from 多面体 (diff: 466)
地球儀 zSortやライティングをちゃんとやると、 やっぱ重くなる。
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();
}
}
