Forked from: yinaak's forked from: forked from: forked from: 10만개 입자를 이용.. diff:1 forked from: forked from: forked from: forked from: 10만개 입자를 이용한 유체 시뮬레이션 실험 alexsandrsok.. forked:0favorite:0lines:166license : All rights reserved modified : 2012-04-19 02:38:40 Embed Tweet // forked from yinaak's forked from: forked from: forked from: 10만개 입자를 이용한 유체 시뮬레이션 실험 // forked from monodreamer's forked from: forked from: 10만개 입자를 이용한 유체 시뮬레이션 실험 // forked from ryo_2004's forked from: 10만개 입자를 이용한 유체 시뮬레이션 실험 // forked from jidolstar's 10만개 입자를 이용한 유체 시뮬레이션 실험 // forked from nulldesign's Liquid10000 package { import flash.display.*; import flash.events.*; import flash.geom.*; import flash.utils.*; import flash.filters.*; import net.hires.debug.Stats; [SWF(width="465", height="465", backgroundColor="0x000000", frameRate="60")]; /** * BitmapData를 이용한 파티클 렌더링 속도 테스트 * 1. lock, unlock 추가 -> 기존보다 frameRate 2이상 증가 (12) * 2. fillRect을 setPixel로 전환 -> 기존보다 frameRate 25~30이상 증가 (40) * 3. point를 number로 전환 -> 기존보다 frameRate 10이상 증가 (50) * 4. array를 vector로 변환 -> 기존보다 frameRate 변화거의 없음 * 5. vector를 linked list로 변환 -> 기존보다 frameRate가 5이상 줄어듬(45) * 6. 4로부터 vectorDat 사이즈를 줄임 -> 기존보다 frameRate 10이상 증가(60이상) * @see http://clockmaker.jp/blog/2009/04/particle/ */ public class bitmap_liquid100000_06 extends Sprite { private const nums:uint = 50000; private var bmpDat:BitmapData; private var vectorDat:BitmapData; private var bmp:Bitmap; private var vectorList:Vector.<VectorDat>; private var rect:Rectangle; private var cTra:ColorTransform; private var timer:Timer; //private var outWidth:int; private var outData:Vector.<uint>; private var loader:ImageLoader; public function bitmap_liquid100000_06() { loader = new ImageLoader(); loader.addEventListener(Event.COMPLETE, initialize); loader.loadImg(); // initialize(); } private function initialize(e:Event=null):void { //stage 관련의 설정 stage.align=StageAlign.TOP_LEFT; stage.scaleMode=StageScaleMode.NO_SCALE; stage.frameRate = 60; //파티클이 렌더링 되는 메인 Bitmap. bmpDat=new BitmapData(465, 465, false, 0x0); bmp=new Bitmap(bmpDat); addChild(bmp); //파티클의 가속도를 계산하기 위한 도움 BitmapData로서 perlinNoise가 적용된다. vectorDat= new BitmapData( 28, 28, false, 0x0 ); seed=Math.floor(Math.random() * 0xFFFF); vectorDat.perlinNoise(28, 28, 4, seed, false, true, 2|4, false, offset ); //addChild(new Bitmap(vectorDat)); //만약 이 perlinNoise가 적용된 Bitmap을 보고 싶다면 주석을 풀자 mapRect = vectorDat.rect; mapWidth = vectorDat.width; //outWidth = bmpDat.width; //outData = new Vector.<uint>(bmpDat.width * bmpDat.height, false); mapData = new Vector.<uint>(vectorDat.width * vectorDat.height, true); //화면크기 rect=new Rectangle(0, 0, 465, 465); //파티클 궤적을 그리기 위함 cTra = new ColorTransform(1, 1, 1, .8); //파티클을 넣기 위한 List vectorList = new Vector.<VectorDat>(nums, true); for (var i:uint=0; i < nums; i++) { //파티클 위치 var px:Number=Math.random() * 465; var py:Number=Math.random() * 465; //파티클 위치,가속도,속도 정보를 List에 저장 vectorList[i] = new VectorDat(px,py); } //지속적인 파티클 렌더링을 위한 loop 함수 호출 addEventListener(Event.ENTER_FRAME, loop); //500ms마다 timer = new Timer(500, 0); timer.addEventListener(TimerEvent.TIMER, resetFunc); timer.start(); // overlay addChild(loader); //통계 addChild(new Stats); //Flash가 Active될때 동작 //stage.addEventListener(Event.ACTIVATE,function($e:Event):void {stage.frameRate=110}); //Flash가 Deactive될때 중지 //stage.addEventListener(Event.DEACTIVATE,function($e:Event):void {stage.frameRate=0.01}); } private var tCounter:int=0; private var ep:Point = new Point(); private var blur:BlurFilter = new BlurFilter(4,4,1); private function loop(e:Event):void { bmpDat.lock(); //렌더링용 BitmapData를 colorTransform로 어둡게 하여 기존에 그려진 파티클의 궤적을 보이도록 함 bmpDat.colorTransform(rect, cTra); bmpDat.applyFilter(bmpDat, rect, ep, blur); //bmpDat.fillRect(rect, 0x0); //outData = bmpDat.getVector(rect); //outData.length = 0; //outData.length = dataLength; //파티클의 위치를 재계산하여 렌더링한다. var col:uint; var dots:VectorDat; var posX:Number; var posY:Number; var idx:int; // 결론 . 파티클에선 벡터가 구린듯? for (var i:uint=0; i < nums; i++) { dots = vectorList[i]; posX = dots.px; posY = dots.py; //col = vectorDat.getPixel(dots.px>>4, dots.py>>4); //idx = (dots.px>>4)|(dots.py>>4)&mapWidth idx = (posX>>4)|(posY>>4); col = mapData[idx]; //dots.next(col); posX += (dots.vx += (dots.ax += ((col & 0xff) - 128) * .0005)); posY += (dots.vy += (dots.ay += ((col >> 8 & 0xff) - 128) * .0005)); //속도와 가속도가 계속 증가하는 것을 방지 dots.ax*=.96; dots.ay*=.96; dots.vx*=.92; dots.vy*=.92; if (posX<0 || posX>465) posX = (posX+465)%465; if (posY<0 || posY>465) posY = (posY+465)%465; //1*1 pixel을 bitmapData에 렌더링 //col = (0xff*transR<<16|0xff*transG<<8|0xff*transB) bmpDat.setPixel( posX, posY, 0xffffff ); dots.px = posX; dots.py = posY; //idx = (posX|0) + (posY|0)*465; //outData[idx] = col;//0xffffffff; } //bmpDat.setVector(rect, outData); loader.colorTrans(); bmpDat.unlock(); if (++tCounter<127) return; tCounter = 0; loader.change(); } private var seed:Number = Math.floor( Math.random() * 0xFFFF ); private var offset:Array = [new Point(), new Point()]; private var mapData:Vector.<uint> ; private var mapRect:Rectangle; private var mapWidth:Number; //private var vR:Number=0, vG:Number=0, vB:Number=0; private function resetFunc(e:Event) :void{ //파티클의 가속도를 계산하기 위한 도움 BitmapData로서 perlinNoise를 변경 vectorDat.perlinNoise( 20, 20, 3, seed, false, true, 2|4, false, offset ); offset[0].x += 1.5; offset[1].y += 1.5; //seed = Math.random()*uint.MAX_VALUE; mapData = vectorDat.getVector(mapRect); mapData.fixed = true; //파티클 궤적을 표시하기 위한 부분을 변경(조금씩 색변동이 일어난다) /* var dots:VectorDat = vectorList[0]; vR += .0001 * (dots.px-232)/465; vG += .0001 * (dots.py-232)/465; vB += .0001 * ((dots.px+dots.py)*.5 -232)/465 ( vR > .2 ) ? vR = .2: ( vR < -.2 ) ? vR = -.2:0; ( vG > .2 ) ? vG = .2: ( vG < -.2 ) ? vG = -.2:0; ( vB > .2 ) ? vB = .2: ( vB < -.2 ) ? vB = -.2:0; cTra.redMultiplier += vR; cTra.blueMultiplier += vB; cTra.greenMultiplier += vG; ( cTra.redMultiplier > .9 ) ? cTra.redMultiplier = .9: ( cTra.redMultiplier < .5 ) ? cTra.redMultiplier = .5:cTra.redMultiplier; ( cTra.blueMultiplier > .9 ) ? cTra.blueMultiplier = .9: ( cTra.blueMultiplier < .5 ) ? cTra.blueMultiplier = .5:cTra.blueMultiplier; ( cTra.greenMultiplier > .9 ) ? cTra.greenMultiplier = .9: ( cTra.greenMultiplier < .5 ) ? cTra.greenMultiplier = .5:cTra.greenMultiplier; //loader.bitmapData.colorTransform(rect, cTra); */ } } } import flash.events.IOErrorEvent; import flash.system.Security; class VectorDat { public var vx:Number = 0; public var vy:Number = 0; public var ax:Number = 0; public var ay:Number = 0; public var px:Number; public var py:Number; public function VectorDat( px:Number, py:Number ) { this.px = px; this.py = py; } } import flash.events.Event; import flash.net.*; import flash.display.*; import flash.geom.*; import flash.filters.BlurFilter; import flash.system.LoaderContext; class ImageLoader extends Bitmap { private var rect:Rectangle; private var cTra:ColorTransform = new ColorTransform(1,1,1,1,-1,0,1); private var colorArr:Array = [-1,0,1,0]; public function loadImg():void { Security.loadPolicyFile('http://monodreamer.cafe24.com/test/crossdomain.xml'); var loader:Loader = new Loader(); var req:URLRequest = new URLRequest("http://monodreamer.cafe24.com/test/Koch_snowflake_(RGB-CMY).jpg"); loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler); loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler); loader.load(req, new LoaderContext(true)); } public function change():void { colorArr.push(colorArr.shift()); cTra.redOffset = colorArr[0]; cTra.blueOffset = colorArr[1]; cTra.greenOffset = colorArr[2]; } public function colorTrans():void { bitmapData.colorTransform(rect, cTra); } private function ioErrorHandler($e:IOErrorEvent):void { bitmapData = new BitmapData(465, 465, false, 0xffffff); bitmapData.perlinNoise( 465, 465, 6, uint.MAX_VALUE, true, true, 1|2|4, false); bitmapData.applyFilter(bitmapData, bitmapData.rect, new Point(), new BlurFilter(32,32,1)); rect = bitmapData.rect; width = height = 465; blendMode = "overlay"; dispatchEvent( new Event(Event.COMPLETE) ); } private function completeHandler($e:Event):void { bitmapData = Bitmap($e.target.content).bitmapData; bitmapData.applyFilter(bitmapData, bitmapData.rect, new Point(), new BlurFilter(32,32,2)); rect = bitmapData.rect; width = height = 465; blendMode = "overlay"; dispatchEvent( new Event(Event.COMPLETE) ); } } Code Fullscreen Preview Fullscreen