// forked from Nao_u's テクスチャ生成実験 // // 波紋+環境マップ // // マウスカーソルの位置に波が起きる // package { import flash.display.Sprite; import flash.events.*; [SWF(width="465", height="465", backgroundColor="0xFFFFFF", frameRate="60")] public class FlashTest extends Sprite { public function FlashTest() { Main = this; startLoad(); stage.addEventListener(Event.ENTER_FRAME,update); } } } import flash.display.*; import flash.events.* import flash.text.TextField; import flash.geom.*; import flash.utils.getTimer; import flash.ui.Keyboard; import flash.net.*; var Main:Sprite; var SCREEN_W:Number = 465; var SCREEN_H:Number = 465; var Text:TextField var Tex:ProcTex; var BITMAP_W:int = 465/2; var BITMAP_H:int = 465/2; var TexData: BitmapData; var loaderA:Loader; var loaderB:Loader; var bLoad:Boolean = false; function startLoad():void{ loaderA = new Loader(); loaderA.load( new URLRequest("http://img.f.hatena.ne.jp/images/fotolife/N/Nao_u/20090913/20091231171735.jpg") ); loaderA.contentLoaderInfo.addEventListener( Event.COMPLETE, loadComplete ); } function loadComplete(e:Event):void { loaderB = new Loader(); loaderB.contentLoaderInfo.addEventListener(Event.INIT, initialize); loaderB.loadBytes(loaderA.contentLoaderInfo.bytes); } function initialize(event:Event):void { var loader:Loader = loaderB; TexData = new BitmapData(loader.width, loader.height, false); TexData.draw(loader); Tex = new ProcTex( BITMAP_W, BITMAP_H ); Tex.Bmp.x = 0; Tex.Bmp.y = 0; Text = new TextField(); Text.text = "----"; Text.autoSize = "left"; Main.addChild(Text); bLoad = true; } // 更新 var mxPrev:int; var myPrev:int; var Pow:Number = 1.0; function update(e :Event):void{ var time:int = getTimer(); Tex.draw(); var mx:int = Main.mouseX * BITMAP_W / SCREEN_W; var my:int = Main.mouseY * BITMAP_H / SCREEN_H; Pow += Math.abs(mx - mxPrev) + Math.abs(my - myPrev); if( Pow > 1.0 ) Pow = 1.0; Tex.addPower( mx, my, Pow ); Pow *= 0.5; mxPrev = mx; myPrev = my; var endTime:int = getTimer() - time; Text.text = " 生成時間:" + endTime + "[ms]"; } // テクスチャ生成クラス class ProcTex{ public var BmpData:BitmapData; public var TmpBmpData:BitmapData; public var Bmp:Bitmap; public var Width:int; public var Height:int; public var HeightBuf:Array; public var HeightIdxDst:int; public var HeightIdxSrc0:int; public var HeightIdxSrc1:int; public var BufWidth:int; public var BufHeight:int; public var PixelBufSize:int = 256; public var PixelBuf:Vector.<int>; public function ProcTex( w:int, h:int ){ Width = w; Height = h; BmpData = new BitmapData(Width, Height, false, 0xffffff); Bmp = new Bitmap(BmpData); Bmp.scaleX = 2.0; Bmp.scaleY = 2.0; Main.addChild(Bmp); // 波高バッファの生成 HeightBuf = new Array; BufWidth = Width+2; BufHeight = Height+2; HeightBuf[0] = new Vector.<Number>; HeightBuf[1] = new Vector.<Number>; HeightBuf[2] = new Vector.<Number>; for( var x:int=-1; x<Width+1; x++ ){ for( var y:int=-1; y<Height+1; y++ ){ var idx:int = (x+1) + (y+1)*BufWidth; HeightBuf[0].push( 0 ); HeightBuf[1].push( 0 ); HeightBuf[2].push( 0 ); } } // 環境マップテクスチャバッファの生成 PixelBuf = new Vector.<int>; for( x=0; x<PixelBufSize; x++ ){ for( y=0; y<PixelBufSize; y++ ){ var col:int = TexData.getPixel(x, y); PixelBuf.push(col); } } HeightIdxSrc0=0; HeightIdxSrc1=1; HeightIdxDst=2; } public function draw():void{ HeightIdxSrc0++; HeightIdxSrc1++; HeightIdxDst++; if( HeightIdxSrc0 > 2 ) HeightIdxSrc0 = 0; if( HeightIdxSrc1 > 2 ) HeightIdxSrc1 = 0; if( HeightIdxDst > 2 ) HeightIdxDst = 0; calcWave(); createBmp( HeightIdxDst ); } // 水面に力を加える public function addPower( px:int, py:int, pow:Number ):void{ var r:int = 6; var buf:Vector.<Number> = HeightBuf[HeightIdxDst]; for( var lx:int=-r; lx<=r; lx++ ){ for( var ly:int=-r; ly<=r; ly++ ){ const d:Number = Math.sqrt(lx*lx+ly*ly); if (d < r) { var p:Number = Math.cos(Math.PI/2 * d/r); var x:int = px + lx; var y:int = py + ly; if( x < 0 || x >= Width || y < 0 || y >= Height ) break; var idx:int = (x+1) + (y+1)*BufWidth; buf[idx] += pow * p; } } } } // 水面画像の生成 public function createBmp( idx:int ):void{ var buf:Vector.<Number> = HeightBuf[HeightIdxDst]; var col:Number, colU:Number, colL:Number, vecX:Number, vecY:Number; var idx:int, ix:int, iy:int; BmpData.lock(); for( var x:int=0; x<Width; x++ ){ for( var y:int=0; y<Height; y++ ){ idx = (x+1) + (y+1)*BufWidth; col = buf[idx]; colU = buf[idx-BufWidth]; colL = buf[idx-1]; vecX = ((colL - col)*0.55 + 1.0) *128; vecY = ((colU - col)*0.55 + 1.0) *128; ix = vecX; iy = vecY; if( ix < 50 ) ix=50; if( iy < 50 ) iy=50; if( ix > 200 ) ix=200; if( iy > 200 ) iy=200; BmpData.setPixel(x, y, PixelBuf[ix+iy*PixelBufSize]); } } BmpData.unlock(); } // 波計算 public function calcWave():void{ var c1:Number = 0.50; var c2:Number = 0.010; var cc:Number = 1 / (1 + c2); var srcBuf0:Vector.<Number> = HeightBuf[HeightIdxSrc0]; var srcBuf1:Vector.<Number> = HeightBuf[HeightIdxSrc1]; var dstBuf:Vector.<Number> = HeightBuf[HeightIdxDst]; var idx:int, idxU:int, idxD:int, idxL:int, idxR:int; for( var x:int=0; x<Width; x++ ){ for( var y:int=0; y<Height; y++ ){ idx = (x+1) + (y+1)*BufWidth; idxU = (x+1) + (y )*BufWidth; idxD = (x+1) + (y+2)*BufWidth; idxL = (x ) + (y+1)*BufWidth; idxR = (x+2) + (y+1)*BufWidth; dstBuf[idx] = ( srcBuf1[idx] *(2-4*c1) -srcBuf0[idx] * (1-c2) + ( srcBuf1[idxU] + srcBuf1[idxD] + srcBuf1[idxL] + srcBuf1[idxR]) * c1 ) * cc; } } } } 波紋+環境マップ