Perlin Particles HSV variation [optimized]
/**
* Copyright Hasufel ( http://wonderfl.net/user/Hasufel )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/xvDe
*/
// forked from Hasufel's Perlin Particles HSV variation
//update: added vector casting
package {
//******************************************************
//PerlinParticles HSV variation (10K) (optimised version)
//Frocessing's hsv downed the framerate: bye frocessing, hsv2rgb added.
//PerlinNoise is generated with blue and red channels only.
//Blue and red channels influence the x and y of particles.
//@by Hasufel 2010
//*****************************************************/
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.filters.BlurFilter;
import flash.geom.ColorTransform;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.utils.getTimer;
import flash.utils.Timer;
// import net.hires.debug.Stats;
[SWF(width=465, height=465, backgroundColor=0,frameRate=60)]
public class PerlinParticles extends Sprite {
private const _stageW:uint = stage.stageWidth;
private const _stageH:uint = stage.stageHeight;
private const _point:Point = new Point(0,0);
private const _particlesNum:uint = 10000;
private const _blurFilter:BlurFilter = new BlurFilter(16,16,4);//16,16,4 hurts much, we know!
private const _numOct:uint = 4;
private const _perlinSize:uint = 32;
private const _ratioX:Number = (_stageW/_perlinSize)/_stageW;
private const _ratioY:Number = (_stageH/_perlinSize)/_stageH;
private var _perlinData:BitmapData = new BitmapData(_perlinSize,_perlinSize,false,0x000000);
private var _perlinBitmap:Bitmap = new Bitmap(_perlinData);
private var _renderData:BitmapData = new BitmapData(_stageW,_stageH,false,0x000000);
private var _renderRect:Rectangle = new Rectangle(0,0,_stageW,_stageH);
private var _renderBitmap:Bitmap = new Bitmap(_renderData);
private var _offsets:Array = new Array;
private var _freq:Vector.<uint> = new Vector.<uint>(_numOct*2,true);
private var _phase:Vector.<uint> = new Vector.<uint>(_numOct*2,true);
private var _particles:Vector.<Particle> = new Vector.<Particle>(_particlesNum,true);
private var _cc:uint = 0;//color control (h from hsv will vary from that)
public function PerlinParticles (){
addChild(_renderBitmap);
for (var i:uint=0;i<_particlesNum;++i){
createParticle(randomNumber(0,_stageW),randomNumber(0,_stageH),0,0,i);
}
for (i=0;i<_numOct;++i) {
_offsets[_offsets.length] = new Point();
_freq[i>>0] = Math.round(5*Math.random()+1);
_freq[(i+1)>>0] = Math.round(6*Math.random()+1);
_phase[i>>0] = Math.round(2*Math.PI*Math.random());
_phase[(i+1)>>0] = Math.round(2*Math.PI*Math.random());
}
_perlinData.perlinNoise(_perlinSize,_perlinSize,_numOct,128,true,false,7,false,_offsets);
_perlinBitmap.transform.colorTransform = new ColorTransform(1,0,1,1); //remove green channel
//addChild(new Stats());
addEventListener(Event.ENTER_FRAME, renderDisplay);
}
private function renderDisplay(e:Event):void {
_cc = (++_cc)%720;
var t:Number = getTimer()*.0001;
for (var i:uint=0;i<_numOct;++i) {
_offsets[i].x = _perlinSize*Math.cos(_freq[i>>0]*t+_phase[i>>0]);
_offsets[i].y = _perlinSize*Math.sin(_freq[(i+1)>>0]*t+_phase[(i+1)>>0]);
}
_perlinData.perlinNoise(_perlinSize,_perlinSize,4,128,true,false,7,false,_offsets);
var color:uint = hsv2rgb(_cc/2,1,.9);
var r:uint = _particlesNum;
_renderData.lock();
_renderData.applyFilter(_renderData,_renderRect,_point,_blurFilter);
while(r--) {
var v:Particle=_particles[r>>0];
if (v.y>_stageH || v.y<0 || v.x>_stageW || v.x<0){
setProps(v, {x:randomNumber(0,_stageW),y:randomNumber(0,_stageH),vx:0,vy:0});
}
var c:uint = _perlinData.getPixel(v.x*_ratioX,v.y*_ratioY);
var red:uint = c>>16;
var blue:uint = c&0xFF;
v.vx += 48-red;
v.vy += 48-blue;
v.x+= v.vx *.005;
v.y+= v.vy *.005;
_renderData.setPixel(v.x,v.y,color);
}
_renderData.unlock();
}
private function hsv2rgb(h:Number,s:Number,v:Number):uint{
/*
s = s > 1 ? 1 : (s < 0 ? 0 : s);
//v = v > 1 ? 1 : (v < 0 ? 0 : v);
//if (s == 0) return v * 0xFF << 16 | v * 0xFF << 8 | v * 0xFF << 0;
h = h >= 360 ? h % 360 : (h < 0 ? h % 360 + 360 : h);
*/
var i:int = int(h/60);
var f:Number = h/60-i;
var p:Number = v*(1-s);
var q:Number = v*(1-s*f);
var t:Number = v*(1-s*(1-f));
switch (i) {
case 0: return v * 0xFF << 16 | t * 0xFF << 8 | p * 0xFF << 0;
case 1: return q * 0xFF << 16 | v * 0xFF << 8 | p * 0xFF << 0;
case 2: return p * 0xFF << 16 | v * 0xFF << 8 | t * 0xFF << 0;
case 3: return p * 0xFF << 16 | q * 0xFF << 8 | v * 0xFF << 0;
case 4: return t * 0xFF << 16 | p * 0xFF << 8 | v * 0xFF << 0;
case 5: return v * 0xFF << 16 | p * 0xFF << 8 | q * 0xFF << 0;
}
return 0;
}
private function createParticle(xx:int,yy:int,vx:Number,vy:Number,i:uint):void {
var p:Particle=new Particle();
setProps(p,{x:xx,y:yy,vx:vx,vy:vy});
_particles[i>>0] = p;
}
private function setProps(o:*,p:Object):void {
for (var k:String in p) {o[k]=p[k];}
}
private function randomNumber(low:int, high:int):int{
return Math.round(Math.random() * (high - low) + low);
}
}
}
final class Particle {
public var x:int;
public var y:int;
public var vx:Number;
public var vy:Number;
}