Chapter 38 Example 3
/**
* Copyright actionscriptbible ( http://wonderfl.net/user/actionscriptbible )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/eFp0
*/
package {
import flash.display.*;
import flash.events.*;
import flash.geom.*;
import flash.net.*;
public class ch38ex3 extends Sprite {
protected const URL_BASE:String = "http://actionscriptbible.com/files/";
protected const INITIAL_PARTICLES:int = 1000;
protected const WELL_GRAVITY_MAX:Number = 5000;
protected var W:int, H:int;
protected var generatorShader:Shader;
protected var stepShader:Shader;
protected var forcemap:BitmapData;
protected var particleData:Vector.<Number>; //4 channels: px,py,vx,vy
protected var bmp:BitmapData;
protected var bitmap:Bitmap;
protected const DIM:ColorTransform = new ColorTransform(.9, .9, .9, .95);
public function ch38ex3() {
stage.frameRate = 60;
loadShader("GravitySimGenerateMap.pbj", onGeneratorShaderReady);
}
protected function loadShader(url:String, onComplete:Function):void {
var loader:URLLoader = new URLLoader(new URLRequest(URL_BASE + url));
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, onComplete);
}
protected function onGeneratorShaderReady(event:Event):void {
event.target.removeEventListener(Event.COMPLETE, onGeneratorShaderReady);
generatorShader = new Shader(URLLoader(event.target).data);
forcemap = new BitmapData(stage.stageWidth, stage.stageHeight, false, 0);
W = forcemap.width; H = forcemap.height;
var forceBitmap:Bitmap = new Bitmap(forcemap);
addChild(forceBitmap);
bmp = new BitmapData(W, H, false, 0);
bitmap = new Bitmap(bmp);
addChild(bitmap);
bitmap.alpha = .99;
initializeParticles();
initializeWells();
loadShader("GravitySimStep.pbj", onStepReady);
}
protected function onStepReady(event:Event):void {
event.target.removeEventListener(Event.COMPLETE, onGeneratorShaderReady);
stepShader = new Shader(URLLoader(event.target).data);
stage.addEventListener(MouseEvent.CLICK,
function(event:Event):void{initializeParticles()});
stage.addEventListener(KeyboardEvent.KEY_UP,
function(event:Event):void{initializeWells()});
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
protected function initializeParticles():void {
var r:Function = Math.random;
particleData = new Vector.<Number>();
for (var i:int = 0; i < INITIAL_PARTICLES; i++) {
particleData.push(r()*W, r()*H, (r()-0.5)*4, (r()-0.5)*4);
}
}
protected function initializeWells():void {
var r:Function = Math.random;
var data:ShaderData = generatorShader.data;
data.power.value = [1.4];
data.star0.value = [r()*W/2 + W/4, r()*H/2 + H/4, r()*WELL_GRAVITY_MAX];
data.star1.value = [r()*W/2 + W/4, r()*H/2 + H/4, r()*WELL_GRAVITY_MAX];
var shaderJob:ShaderJob = new ShaderJob(generatorShader, forcemap);
shaderJob.start(true);
}
protected function step():void {
var data:ShaderData = stepShader.data;
data.forcemap.input = forcemap;
data.inpoints.input = particleData;
data.inpoints.height = 1;
data.inpoints.width = particleData.length/4;
var shaderJob:ShaderJob = new ShaderJob(stepShader, particleData,
particleData.length/4, 1);
shaderJob.start(true);
}
protected function draw():void {
bmp.colorTransform(bmp.rect, DIM);
bmp.lock();
for (var i:int = 0; i < particleData.length; i+=4) {
bmp.setPixel(particleData[i], particleData[i+1], 0xffffff);
}
bmp.unlock();
}
protected function onEnterFrame(event:Event):void {
step();
draw();
}
}
}
/***********************
<languageVersion : 1.0;>
kernel GravitySimGenerateMap
< namespace : "com.actionscriptbible";
vendor : "ActionScript 3.0 Bible";
version : 1;
description : "Generates a force map from two stars";
>
{
parameter float3 star0;
parameter float3 star1;
parameter float power <defaultValue: float(2.0);>;
input image4 src;
output pixel4 dst;
void evaluatePixel() {
float2 point = outCoord();
float2 totalForce = float2(0.0);
float2 force;
float dist;
//unrolled loop iteration 0
force = star0.xy - point;
dist = length(force);
force = normalize(force);
force *= star0.z / (pow(dist, power));
totalForce += force;
//unrolled loop iteration 1
force = star1.xy - point;
dist = length(force);
force = normalize(force);
force *= star1.z / (pow(dist, power));
totalForce += force;
totalForce = clamp(totalForce, -100.0, 100.0) + 100.0;
totalForce /= 200.0;
dst = pixel4(0.0, 0.0, 0.0, 1.0);
dst.rg = totalForce.xy;
}
}
************************************
<languageVersion : 1.0;>
kernel GravitySimStep
< namespace : "com.actionscriptbible";
vendor : "ActionScript 3.0 Bible";
version : 1;
description : "Gravity simulation step";
>
{
parameter float2 scale <defaultValue: float2(1.0, 1.0);>;
input image3 forcemap;
input image4 inpoints;
output pixel4 outpoint;
void evaluatePixel() {
//each input pixel represents a point mass (particle) with mass=1
//inpoint.XY = <x, y> position
//inpoint.ZW = <x, y> velocity
float4 particle = sampleNearest(inpoints, outCoord());
//the forcemap at a pixel stores the force vector at that point
//forcemap[x, y].RG = <x, y> force vector (normalized... 0.5 = 0)
float2 force = sampleNearest(forcemap, particle.xy).rg;
force = (force - float2(0.5)) * scale;
float2 velocity = particle.zw + force;
float2 position = particle.xy + velocity;
outpoint.xy = position;
outpoint.zw = velocity;
}
}
**************************************/