Home > 梅原 > 空模様

空模様

20090607
Category:梅原 /Tags:

空模様3DのテクスチャーとしてBitmapをなんとかきれいに貼り付けられるようになった頃、さてこの方法ではどれくらいのスピードが出るのだろうか?と疑問に思ってテストとして作ったもの(wonderflでも動くように、細々と書き換えたけど)。

30fps640*480のflvを読み込み、再生しっぱなしにして、それを4つの面のBitmapDataに対してdrawしている。
結果、とりあえず目的に対しては十分に高速であることがわかった。

この画像をクリックしてください。

画像をクリックするとswfが開きます。

/*
 * 3DのテクスチャーとしてBitmapをなんとかきれいに貼り付けられるようになった頃、
 * さてこの方法ではどれくらいのスピードが出るのだろうか?
 * と疑問に思ってテストとして作ったもの(wonderflでも動くように、
 * 細々と書き換えたけど)。
 *
 * 30fps640*480のflvを読み込み、再生しっぱなしにして、
 * それを4つの面のBitmapDataに対してdrawしている。
 * 結果、とりあえず目的に対しては十分に高速であることがわかった。
 *
 * */
package
{
	import flash.display.Sprite;
	import net.hires.debug.Stats;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.NetStatusEvent;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	import flash.media.Video;
	import flash.display.BitmapData;
	import flash.system.Security;
	[SWF(backgroundColor="0x000000")]
	/**
	 * ...
	 * @author umhr
	 */
	public class Main extends Sprite
	{
		private var Math3d:Math3dClass = new Math3dClass();
		private var Poz:PozClass = new PozClass();
		private var sp_array:Array = new Array();
		private var Render:RenderClass = new RenderClass();
		private var stgeW:int = stage.stageWidth / 2;
		private var stgeH:int = stage.stageHeight / 2;
		private var baseURL:String = "";
		function Main() {
			 if(isMztmjp()){
            }else{
                baseURL = "http://mztm.heteml.jp/umhr/mztmjpwp/";
				Security.loadPolicyFile("http://mztm.heteml.jp/crossdomain.xml");
            }

			Math3d.focalLength = 1000;

			var Texture:TextureClass = new TextureClass();
			addChild(new Stats());
			stage.scaleMode = "noScale";

			setModel();
			var connection:NetConnection = new NetConnection();
			connection.connect(null);
			var netStream:NetStream = new NetStream(connection);
			netStream.addEventListener (NetStatusEvent.NET_STATUS ,NET_STATUS);
			function NET_STATUS (event : NetStatusEvent):void {
				switch(event.info.code){
				case "NetStream.Play.Stop":
					netStream.seek(0);
					break;
				}
			}
			netStream.client = new Object();
			netStream.play(baseURL+"umhr_pcloud14.flv");
			var video_obj : Video = new Video(640,480);
			video_obj.attachNetStream(netStream);

			stage.addEventListener(Event.ENTER_FRAME,ENTER_FRAME);
			function ENTER_FRAME(e:Event):void {
				Poz.global_array[3] += (stage.mouseY-stgeH)/20000;
				Poz.global_array[4] += (stage.mouseX-stgeW)/20000;
				var poz_array:Array = new Array();
				poz_array = Math3d.arrayClone(Poz.model_array);
				Math3d.localAffine(poz_array,Poz.local_array);
				Math3d.globalAffine(poz_array,Poz.global_array);
				Math3d.perspective(poz_array);
				Poz.zSort(poz_array,sp_array,stage);

				render(poz_array);
			}

			function render(poz_array:Array):void{
				var _length:int = poz_array.length;
				var bmp_data : BitmapData = new BitmapData(640 , 480 , false , 0x111111);
				bmp_data.draw(video_obj);
				for (var i:int = 0; i<_length; i++) {
					var _sp:Sprite = sp_array[i];
					_sp.graphics.clear();
					Render.drawQuadrangleImage22(_sp,poz_array[i],bmp_data);
				}
			}

			stage.addEventListener(MouseEvent.CLICK,onClick);
		}
		private function isMztmjp():Boolean{
            var _str:String = stage.loaderInfo.url;
            return (_str.substr(0,5) == "file:" || _str.indexOf("mztm.jp") > -1);

        }
		private function onClick(e:MouseEvent):void {
			Render.isDrawQuadrangleImage22Line = !Render.isDrawQuadrangleImage22Line;
		}
		private function setModel():void{
			Poz.local_array[0] = [0,0,240,Math.PI,0,0];
			Poz.local_array[1] = [0,0,-240,0,0,0];
			Poz.local_array[2] = [0,240,0,-Math.PI/2,0,0];
			Poz.local_array[3] = [0,-240,0,Math.PI/2,0,0];
			var _length:int = Poz.local_array.length;
			for (var i:int = 0; i<_length; i++) {
				Poz.model_array[i] = [[0,0,0],[-320,-240,0],[0,-240,0],[320,-240,0],[-320,0,0],[0,0,0],[320,0,0],[-320,240,0],[0,240,0],[320,240,0]];
				Poz.localTo_array[i] = Math3d.arrayClone(Poz.local_array[i]);
				sp_array[i] = new Sprite();
				sp_array[i].x = stgeW;
				sp_array[i].y = stgeH;
				stage.addChild(sp_array[i]);
			}
		}
	}
}
////////////////
	class RenderClass{
		import flash.display.Sprite;
		import flash.geom.Matrix;
		import flash.display.BitmapData;
		import flash.media.Video;
		//クラスプロパティ
		//クラスメソッド
		//コンストラクタ
		public var isDrawQuadrangleImage22Line:Boolean;
		public function RenderClass(){
			//trace("RenderClass imported");
		 }
		//インスタンスプロパティ
		//public var defaultColor:int = 0xff0000;

		public function drowLine(_sp:Sprite,poz_array:Array,_thickness:Number = 0,_color:int = 0xFF0000,_alpha:Number = 1):void{
			//if(_color == -1){_color = defaultColor};
			_sp.graphics.lineStyle(_thickness,_color,_alpha)
			_sp.graphics.beginFill (1,0xFF3333);
			var _l:int = poz_array.length;
			_sp.graphics.moveTo(poz_array[_l-1][0],poz_array[_l-1][1]);
			for (var j:int = 0; j<_l; j++) {
				_sp.graphics.lineTo(poz_array[j][0],poz_array[j][1]);
			}
			_sp.graphics.lineStyle()
		}

		public function drawQuadrangleImage(_sp:Sprite,poz_array:Array,bmp_data:BitmapData):void{
			var bmp_dataW:Number = bmp_data.width;
			var bmp_dataH:Number = bmp_data.height;
			var _matrix:Matrix = setMatrix(poz_array[0],poz_array[1],poz_array[2],bmp_dataW,bmp_dataH);
			_sp.graphics.beginBitmapFill(bmp_data, _matrix, false, false);
			_sp.graphics.moveTo(poz_array[0][0],poz_array[0][1]);
			_sp.graphics.lineTo(poz_array[1][0],poz_array[1][1]);
			_sp.graphics.lineTo(poz_array[2][0],poz_array[2][1]);
			_sp.graphics.endFill();

			var _ltX:Number = poz_array[2][0] - poz_array[3][0] + poz_array[1][0];
			var _ltY:Number = poz_array[2][1] - poz_array[3][1] + poz_array[1][1];
			_matrix = setMatrix([_ltX,_ltY],poz_array[1],poz_array[2],bmp_dataW,bmp_dataH);
			_sp.graphics.beginBitmapFill(bmp_data, _matrix, false, false);
			_sp.graphics.moveTo(poz_array[1][0],poz_array[1][1]);
			_sp.graphics.lineTo(poz_array[2][0],poz_array[2][1]);
			_sp.graphics.lineTo(poz_array[3][0],poz_array[3][1]);
			_sp.graphics.endFill();
		}

		public function drawQuadrangleImage22(_sp:Sprite,poz_array:Array,bmp_data:BitmapData):void{
			var bmp_dataW:Number = bmp_data.width/2;
			var bmp_dataH:Number = bmp_data.height/2;
			var _matrix:Matrix = setMatrix(poz_array[1],poz_array[2],poz_array[4],bmp_dataW,bmp_dataH);
			_sp.graphics.beginBitmapFill(bmp_data, _matrix, false, false);
			if(isDrawQuadrangleImage22Line){
				_sp.graphics.lineStyle(1)
			}

			_sp.graphics.moveTo(poz_array[1][0],poz_array[1][1]);
			_sp.graphics.lineTo(poz_array[2][0],poz_array[2][1]);
			_sp.graphics.lineTo(poz_array[4][0],poz_array[4][1]);
			_sp.graphics.endFill();

			var _ltX:Number = poz_array[4][0] - poz_array[5][0] + poz_array[2][0];
			var _ltY:Number = poz_array[4][1] - poz_array[5][1] + poz_array[2][1];
			_matrix = setMatrix([_ltX,_ltY],poz_array[2],poz_array[4],bmp_dataW,bmp_dataH);
			_sp.graphics.beginBitmapFill(bmp_data, _matrix, false, false);
			_sp.graphics.moveTo(poz_array[2][0],poz_array[2][1]);
			_sp.graphics.lineTo(poz_array[5][0],poz_array[5][1]);
			_sp.graphics.lineTo(poz_array[4][0],poz_array[4][1]);
			_sp.graphics.endFill();

			_matrix = setMatrix1(poz_array[2],poz_array[3],poz_array[5],bmp_dataW,bmp_dataH);
			_sp.graphics.beginBitmapFill(bmp_data, _matrix, false, false);
			_sp.graphics.moveTo(poz_array[2][0],poz_array[2][1]);
			_sp.graphics.lineTo(poz_array[3][0],poz_array[3][1]);
			_sp.graphics.lineTo(poz_array[5][0],poz_array[5][1]);
			_sp.graphics.endFill();

			_ltX = poz_array[5][0] - poz_array[6][0] + poz_array[3][0];
			_ltY = poz_array[5][1] - poz_array[6][1] + poz_array[3][1];
			_matrix = setMatrix1([_ltX,_ltY],poz_array[3],poz_array[5],bmp_dataW,bmp_dataH);
			_sp.graphics.beginBitmapFill(bmp_data, _matrix, false, false);
			_sp.graphics.moveTo(poz_array[3][0],poz_array[3][1]);
			_sp.graphics.lineTo(poz_array[5][0],poz_array[5][1]);
			_sp.graphics.lineTo(poz_array[6][0],poz_array[6][1]);
			_sp.graphics.endFill();

			_matrix = setMatrix2(poz_array[4],poz_array[5],poz_array[7],bmp_dataW,bmp_dataH);
			_sp.graphics.beginBitmapFill(bmp_data, _matrix, false, false);
			_sp.graphics.moveTo(poz_array[4][0],poz_array[4][1]);
			_sp.graphics.lineTo(poz_array[5][0],poz_array[5][1]);
			_sp.graphics.lineTo(poz_array[7][0],poz_array[7][1]);
			_sp.graphics.endFill();

			_ltX = poz_array[7][0] - poz_array[8][0] + poz_array[5][0];
			_ltY = poz_array[7][1] - poz_array[8][1] + poz_array[5][1];
			_matrix = setMatrix2([_ltX,_ltY],poz_array[5],poz_array[7],bmp_dataW,bmp_dataH);
			_sp.graphics.beginBitmapFill(bmp_data, _matrix, false, false);
			_sp.graphics.moveTo(poz_array[5][0],poz_array[5][1]);
			_sp.graphics.lineTo(poz_array[7][0],poz_array[7][1]);
			_sp.graphics.lineTo(poz_array[8][0],poz_array[8][1]);
			_sp.graphics.endFill();

			_matrix = setMatrix3(poz_array[5],poz_array[6],poz_array[8],bmp_dataW,bmp_dataH);
			_sp.graphics.beginBitmapFill(bmp_data, _matrix, false, false);
			_sp.graphics.moveTo(poz_array[5][0],poz_array[5][1]);
			_sp.graphics.lineTo(poz_array[6][0],poz_array[6][1]);
			_sp.graphics.lineTo(poz_array[8][0],poz_array[8][1]);
			_sp.graphics.endFill();

			_ltX = poz_array[8][0] - poz_array[9][0] + poz_array[6][0];
			_ltY = poz_array[8][1] - poz_array[9][1] + poz_array[6][1];
			_matrix = setMatrix3([_ltX,_ltY],poz_array[6],poz_array[8],bmp_dataW,bmp_dataH);
			_sp.graphics.beginBitmapFill(bmp_data, _matrix, false, false);
			_sp.graphics.moveTo(poz_array[6][0],poz_array[6][1]);
			_sp.graphics.lineTo(poz_array[8][0],poz_array[8][1]);
			_sp.graphics.lineTo(poz_array[9][0],poz_array[9][1]);
			_sp.graphics.endFill();
		}

		private function setMatrix(poz0_array:Array,poz1_array:Array,poz2_array:Array,_w:Number,_h:Number):Matrix{
			var _matrix:Matrix = new Matrix();
			_matrix.a = (poz1_array[0]-poz0_array[0])/_w;
			_matrix.b = (poz1_array[1]-poz0_array[1])/_w;
			_matrix.c = (poz2_array[0]-poz0_array[0])/_h;
			_matrix.d = (poz2_array[1]-poz0_array[1])/_h;
			_matrix.tx = poz0_array[0];
			_matrix.ty = poz0_array[1];
			return _matrix;
		}
		private function setMatrix1(poz0_array:Array,poz1_array:Array,poz2_array:Array,_w:Number,_h:Number):Matrix{
			var _matrix:Matrix = new Matrix();
			_matrix.a = (poz1_array[0]-poz0_array[0])/_w;
			_matrix.b = (poz1_array[1]-poz0_array[1])/_w;
			_matrix.c = (poz2_array[0]-poz0_array[0])/_h;
			_matrix.d = (poz2_array[1]-poz0_array[1])/_h;
			_matrix.tx = poz0_array[0]-(poz1_array[0]-poz0_array[0]);
			_matrix.ty = poz0_array[1]-(poz1_array[1]-poz0_array[1]);
			return _matrix;
		}
		private function setMatrix2(poz0_array:Array,poz1_array:Array,poz2_array:Array,_w:Number,_h:Number):Matrix{
			var _matrix:Matrix = new Matrix();
			_matrix.a = (poz1_array[0]-poz0_array[0])/_w;
			_matrix.b = (poz1_array[1]-poz0_array[1])/_w;
			_matrix.c = (poz2_array[0]-poz0_array[0])/_h;
			_matrix.d = (poz2_array[1]-poz0_array[1])/_h;
			_matrix.tx = poz0_array[0]-(poz2_array[0]-poz0_array[0]);
			_matrix.ty = poz0_array[1]-(poz2_array[1]-poz0_array[1]);
			return _matrix;
		}
		private function setMatrix3(poz0_array:Array,poz1_array:Array,poz2_array:Array,_w:Number,_h:Number):Matrix{
			var _matrix:Matrix = new Matrix();
			_matrix.a = (poz1_array[0]-poz0_array[0])/_w;
			_matrix.b = (poz1_array[1]-poz0_array[1])/_w;
			_matrix.c = (poz2_array[0]-poz0_array[0])/_h;
			_matrix.d = (poz2_array[1]-poz0_array[1])/_h;
			_matrix.tx = poz0_array[0]-(poz2_array[0]-poz0_array[0])-(poz1_array[0]-poz0_array[0]);
			_matrix.ty = poz0_array[1]-(poz2_array[1]-poz0_array[1])-(poz1_array[1]-poz0_array[1]);
			return _matrix;
		}
		//インスタンスメソッド

	}
////////////////
	class PozClass{
		//クラスプロパティ
		//クラスメソッド
		//コンストラクタ
		public function PozClass(){
			//trace("Math3d imported");
		 }
		//インスタンスプロパティ

		//globalの座標[x,y,z,xr,yr,zr];
		public var global_array:Array = new Array(0,0,0,0,0,0);
		public var globalTo_array:Array = new Array(0,0,0,0,0,0);
		public var local_array:Array = new Array();
		public var localTo_array:Array = new Array();

		public var model_array:Array = new Array();

		//インスタンスメソッド
		public function zSort(poz_array:Array,sp_array:Array,target:Object):void{
			var _length:int = poz_array.length;
			var z_array:Array = new Array();
			for (var i:int = 0; i<_length; i++) {
				z_array[i] = poz_array[i][0][2];
			}
			z_array = z_array.sort(Array.NUMERIC|Array.RETURNINDEXEDARRAY|Array.DESCENDING);
			for (var j:int = 0; j<_length; j++) {
				var _z:int =	z_array[j];
				target.setChildIndex(sp_array[_z],0);
			}
		}

	}

////////////////
	class TextureClass{
		//import flash.display.Sprite;
		import flash.geom.Matrix;
		import flash.display.BitmapData;
		//クラスプロパティ
		//クラスメソッド
		//コンストラクタ
		public function TextureClass(){
			//trace("RenderClass imported");
		 }
		//インスタンスプロパティ
		public var bmp11_array:Array = new Array();
		public var bmp22_array:Array = new Array();

		//画像をbitmapData化して、arrayに入れる。
		public function setBmp11(img_array:Array):void{
			var _length:int = img_array.length;
			for (var i:int = 0; i<_length; i++) {
				var imgW:int = img_array[i].width;
				var imgH:int = img_array[i].height;
				var bmp_data:BitmapData = new BitmapData(imgW,imgH, true, 0x00FFFFFF);
				bmp_data.draw(img_array[i]);
				bmp11_array[i] = bmp_data;
			}
		}

		//画像をbitmapData化して、arrayに入れる。2*2の4分割用。
		public function setBmp22(img_array:Array):void{
			var _length:int = img_array.length;
			for (var i:int = 0; i<_length; i++) {
				var imgW:int = img_array[i].width;
				var imgH:int = img_array[i].height;

				var Q_array:Array = new Array();
				var mQ:Matrix = new Matrix(1,0,0,1,0,0);
				var bmpQ0_data:BitmapData = new BitmapData(imgW/2,imgH/2, true, 0x00FFFFFF);
				bmpQ0_data.draw(img_array[i],mQ);
				Q_array[0] = bmpQ0_data;

				var bmpQ1_data:BitmapData = new BitmapData(imgW/2,imgH/2, true, 0x00FFFFFF);
				mQ.tx= -imgW/2;
				bmpQ1_data.draw(img_array[i],mQ);
				Q_array[1] = bmpQ1_data;

				var bmpQ2_data:BitmapData = new BitmapData(imgW/2,imgH/2, true, 0x00FFFFFF);
				mQ.tx= 0;
				mQ.ty= -imgH/2;
				bmpQ2_data.draw(img_array[i],mQ);
				Q_array[2] = bmpQ2_data;

				var bmpQ3_data:BitmapData = new BitmapData(imgW/2,imgH/2, true, 0x00FFFFFF);
				mQ.tx= -imgW/2;
				bmpQ3_data.draw(img_array[i],mQ);
				Q_array[3] = bmpQ3_data;

				bmp22_array[i] = Q_array;
			}
		}

		//インスタンスメソッド

	}

////////////////
	class Math3dClass{

		//クラスプロパティ
		//クラスメソッド
		//コンストラクタ
		public function Math3dClass(){
			//trace("Math3d imported");
		 }
		//インスタンスプロパティ
		//var angle = 60;	// 視野角?
		public var focalLength:Number = 1000;//焦点距離

		//インスタンスメソッド
		//arrayの複製。再起処理を行っている。
		public function arrayClone(ar:Array):Array {
			var _array:Array = new Array();
			var _len:int = ar.length;
			for (var i:int = 0; i<_len; i++) {
				_array[i]=(ar[i] is Array)?arrayClone(ar[i]):ar[i];
			}
			return _array;
		}

		//二点間の距離を返す関数。
		public function distance(a_array:Array,b_array:Array):Number{
			var _x:Number = a_array[0] - b_array[0];
			var _y:Number = a_array[1] - b_array[1];
			var _z:Number = a_array[2] - b_array[2];
			return Math.sqrt(_x*_x+_y*_y+_z*_z);
		}

		//パースペクティブ
		public function perspective(arg_array:Array):void{
			var _length:int = arg_array.length;
			for (var i:int = 0; i<_length; i++) {
				var j_length:int = arg_array[i].length;
				for (var j:int = 0; j<j_length; j++) {
					var _per:Number = focalLength/(focalLength+arg_array[i][j][2]);
					arg_array[i][j] = [arg_array[i][j][0] * _per,arg_array[i][j][1] * _per,_per];
				}
			}
		}

		//
		//ローカル座標でのアフィン変換Affin transform
		public function localAffine(data_array:Array,poz_array:Array):void {
			var _length:uint = new uint(data_array.length);
			for (var i:int = 0; i<_length; i++) {
				var n_cx:Number = Math.cos(poz_array[i][3]);
				var n_sx:Number = Math.sin(poz_array[i][3]);
				var n_cy:Number = Math.cos(poz_array[i][4]);
				var n_sy:Number = Math.sin(poz_array[i][4]);
				var n_cz:Number = Math.cos(poz_array[i][5]);
				var n_sz:Number = Math.sin(poz_array[i][5]);
				var d_x:Number = poz_array[i][0];
				var d_y:Number = poz_array[i][1];
				var d_z:Number = poz_array[i][2];
				var af_xx:Number = n_cz*n_cy+n_sx*n_sy*n_sz;
				var af_xy:Number = n_sx*n_sy*n_cz-n_sz*n_cy;
				var af_xz:Number = n_sy*n_cx;
				var af_yx:Number = n_cx*n_sz;
				var af_yy:Number = n_cx*n_cz;
				var af_yz:Number = -n_sx;
				var af_zx:Number = n_cy*n_sx*n_sz-n_sy*n_cz;
				var af_zy:Number = n_sy*n_sz+n_cy*n_sx*n_cz;
				var af_zz:Number = n_cx*n_cy;

				var i_length:uint = new uint(data_array[i].length);
				for (var j:uint = 0; j<i_length; j++) {
					var af_x:Number = data_array[i][uint(j)][uint(0)];
					var af_y:Number = data_array[i][uint(j)][uint(1)];
					var af_z:Number = data_array[i][uint(j)][uint(2)];
					data_array[i][uint(j)][uint(0)] = af_x*af_xx+af_y*af_xy+af_z*af_xz+d_x;
					data_array[i][uint(j)][uint(1)] = af_x*af_yx+af_y*af_yy+af_z*af_yz+d_y;
					data_array[i][uint(j)][uint(2)] = af_x*af_zx+af_y*af_zy+af_z*af_zz+d_z;
				}
			}
		}

		//
		//グローバル座標でのアフィン変換Affin transform
		public function globalAffine(data_array:Array,poz_array:Array):void {
			var d_x:Number = poz_array[uint(0)];
			var d_y:Number = poz_array[uint(1)];
			var d_z:Number = poz_array[uint(2)];
			var _cx:Number = Math.cos(poz_array[uint(3)]);
			var _sx:Number = Math.sin(poz_array[uint(3)]);
			var _cy:Number = Math.cos(poz_array[uint(4)]);
			var _sy:Number = Math.sin(poz_array[uint(4)]);
			var _cz:Number = Math.cos(poz_array[uint(5)]);
			var _sz:Number = Math.sin(poz_array[uint(5)]);
			var af_xx:Number = _cz*_cy+_sx*_sy*_sz;
			var af_xy:Number = _sx*_sy*_cz-_sz*_cy;
			var af_xz:Number = _sy*_cx;
			var af_yx:Number = _cx*_sz;
			var af_yy:Number = _cx*_cz;
			var af_yz:Number = -_sx;
			var af_zx:Number = _cy*_sx*_sz-_sy*_cz;
			var af_zy:Number = _sy*_sz+_cy*_sx*_cz;
			var af_zz:Number = _cx*_cy;
			var _length:uint = new uint(data_array.length);
			for (var i:uint = 0; i<_length; i++) {
				var i_length:uint = new uint(data_array[i].length);
				for (var j:uint = 0; j<i_length; j++) {
					var af_x:Number = data_array[i][uint(j)][uint(0)];
					var af_y:Number = data_array[i][uint(j)][uint(1)];
					var af_z:Number = data_array[i][uint(j)][uint(2)];
					data_array[i][uint(j)][uint(0)] = af_x*af_xx+af_y*af_xy+af_z*af_xz+d_x;
					data_array[i][uint(j)][uint(1)] = af_x*af_yx+af_y*af_yy+af_z*af_yz+d_y;
					data_array[i][uint(j)][uint(2)] = af_x*af_zx+af_y*af_zy+af_z*af_zz+d_z;
				}
			}
		}

	}

一応、Wonderflも貼っておく。

関連記事:

Comments are closed.