/**
* Copyright YoupSolo ( http://wonderfl.net/user/YoupSolo )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/gAN9
*/
package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.filters.BitmapFilterQuality;
import flash.filters.BlurFilter;
import flash.geom.ColorTransform;
import flash.geom.Point;
import flash.utils.getTimer;
[SWF(backgroundColor="0x0",frameRate="60",width="465",height="465")]
public class Main extends Sprite
{
private const pi2:Number = Math.PI * 2;
private var displayWidth:Number;
private var displayHeight:Number;
private var projCenterX:Number;
private var projCenterY:Number;
private var theta:Number;
private var phi:Number;
private var dphi:Number;
private var dtheta:Number;
private var fLen:Number;
private var uMax:Number;
private var dColor:uint;
private var cost:Number;
private var sint:Number;
private var cosp:Number;
private var sinp:Number;
private var p:Particle3D;
private var m:Number;
private var numParticles:Number;
private var bgColor:uint;
private var blur:BlurFilter;
private var origin:Point;
private var darken:ColorTransform;
private var picHolder:Sprite;
private var displayBitmapData:BitmapData;
private var firstParticle:Particle3D;
private var M11:Number;
private var M12:Number;
private var M31:Number;
private var M32:Number;
private var level:Number;
private var readColor:uint;
private var levelInc:Number;
private var numT:Number;
private var numS:Number;
private var fadeRate:Number;
private var maxLevelInc:Number;
private var depth0:Number;
private var level0:Number;
private var depth1:Number;
private var level1:Number;
private var colorShift:Array = [16, 8, 0];
private var csi:int = 0;
public function Main()
{
if (stage)
init();
else
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
maxLevelInc = 20;
level0 = 1;
depth0 = -145;
level1 = maxLevelInc;
depth1 = 145;
fadeRate = (maxLevelInc - 1) / (depth1 - depth0);
displayWidth = 400;
displayHeight = 400;
projCenterX = displayWidth >> 1;
projCenterY = displayHeight >> 1;
theta = 3 * Math.PI / 2;
phi = -Math.PI / 4;
dphi = Math.PI / 208;
dtheta = Math.PI / 177;
fLen = 250;
uMax = fLen - 2;
origin = new Point();
blur = new BlurFilter(4, 4);
blur.quality = BitmapFilterQuality.MEDIUM;
var darkenFactor:Number = 3/4;
darken = new ColorTransform(darkenFactor, darkenFactor, darkenFactor);
picHolder = new Sprite();
picHolder.x = 40;
picHolder.y = 40;
displayBitmapData = new BitmapData(displayWidth, displayHeight, false, bgColor);
picHolder.addChild( new Bitmap(displayBitmapData) );
stage.addChild(picHolder);
createParticles();
stage.addEventListener(Event.ENTER_FRAME, _oef);
stage.addEventListener(KeyboardEvent.KEY_UP, _onKeyUp );
}
private function _onKeyUp(e:KeyboardEvent):void
{
csi = (csi + 1) % 3;
}
private function _oef(evt:Event):void
{
dphi = 0.015 * Math.cos(getTimer() * 0.000132);
dtheta = 0.017 * Math.cos(getTimer() * 0.000244);
phi = (phi + dphi) % pi2;
theta = (theta + dtheta) % pi2;
cost = Math.cos(theta);
sint = Math.sin(theta);
cosp = Math.cos(phi);
sinp = Math.sin(phi);
M11 = cost * sinp;
M12 = sint * sinp;
M31 = -cost * cosp;
M32 = -sint * cosp;
displayBitmapData.lock();
displayBitmapData.colorTransform(displayBitmapData.rect, darken);
displayBitmapData.applyFilter(displayBitmapData, displayBitmapData.rect, origin, blur);
p = firstParticle;
do
{
//Calculate rotated coordinates
p.u = M11 * p.x + M12 * p.y + cosp * p.z;
p.v = -sint * p.x + cost * p.y;
p.w = M31 * p.x + M32 * p.y + sinp * p.z;
//Calculate viewplane projection coordinates
m = fLen / (fLen - p.u);
p.projX = p.v * m + projCenterX;
p.projY = p.w * m + projCenterY;
if ((p.projX > displayWidth) || (p.projX < 0) || (p.projY < 0) || (p.projY > displayHeight) || (p.u > uMax))
{
p.onScreen = false;
}
else
{
p.onScreen = true;
}
if (p.onScreen)
{
//we read the color in the position where we will place another particle:
readColor = displayBitmapData.getPixel(p.projX, p.projY);
//levelInc = expInt*Math.exp(expRate*p.u)
levelInc = fadeRate * (p.u - depth0) + 1;
//clamp value of increase
levelInc = (levelInc > maxLevelInc) ? maxLevelInc : (levelInc < 0 ? 0 : levelInc);
level = (readColor >> colorShift[csi]) + levelInc;
//we make sure that 'level' stays smaller than 255:
level = (level > 255) ? 255 : level;
dColor = level << colorShift[csi];
displayBitmapData.setPixel(p.projX, p.projY, dColor);
}
p = p.next;
} while (p != null)
displayBitmapData.unlock();
}
private function createParticles():void
{
var rad1:Number;
var rad2:Number;
var f1:Number;
var f2:Number;
var s:Number;
var t:Number;
var sMin:Number;
var tMin:Number;
var sMax:Number;
var tMax:Number;
var sInc:Number;
var tInc:Number;
sMin = -Math.PI;
sMax = Math.PI;
tMin = -Math.PI;
tMax = Math.PI;
//These are the number of divisions to use for the parameters
numT = 150;
numS = 500;
sInc = (sMax - sMin) / numS;
tInc = (tMax - tMin) / numT;
var s0:Number;
var t0:Number;
var sFuzz:Number = 0;
var tFuzz:Number = 0;
numParticles = numT * numS;
var lastParticle:Particle3D;
//note that in the loop below we only let i go up to numT-1 rather than numT, in order to
//achieve a seamless periodic function. In other words, the maximum t value is not PI, but
//instead one incremental step smaller than PI. We do a similar thing for the s parameter below.
for (var i:int = 0; i < numT; i++)
{
t0 = tMin + tInc * i;
for (var j:int = 0; j < numS; j++)
{
s0 = sMin + sInc * j;
s = s0 + sFuzz * (Math.random() * 2 - 1);
t = t0 + tFuzz * (Math.random() * 2 - 1);
var thisParticle:Particle3D = new Particle3D(0x888888);
rad1 = 105;
rad2 = 27;
f1 = 0.5 * Math.sin(s * 5);
f2 = 0.5 * Math.cos(s * 5);
thisParticle.x = rad1 * Math.cos(s) + (1 + f1) * rad2 * Math.cos(t) * Math.cos(s);
thisParticle.y = rad1 * Math.sin(s) + (1 + f1) * rad2 * Math.cos(t) * Math.sin(s);
thisParticle.z = (1 + f2) * rad2 * Math.sin(t);
if ((i == 0) && (j == 0))
{
firstParticle = thisParticle;
}
else
{
lastParticle.next = thisParticle;
}
lastParticle = thisParticle;
}
}
}
}
}
class Point3D
{
public var x:Number;
public var y:Number;
public var z:Number;
private var outputPoint:Point3D;
public function Point3D(x1:Number = 0, y1:Number = 0, z1:Number = 0)
{
this.x = x1;
this.y = y1;
this.z = z1;
}
public function clone():Point3D
{
outputPoint = new Point3D();
outputPoint.x = this.x;
outputPoint.y = this.y;
outputPoint.z = this.z;
return outputPoint;
}
}
class Particle3D extends Point3D
{
public var next:Particle3D;
public var prev:Particle3D;
public var onScreen:Boolean;
public var vel:Point3D = new Point3D();
public var accel:Point3D = new Point3D();
public var lastX:Number;
public var lastY:Number;
public var lastZ:Number;
public var projX:Number;
public var projY:Number;
public var u:Number;
public var v:Number;
public var w:Number;
public var picX:Number;
public var picY:Number;
public var dest:Array;
public var color:uint;
public var red:Number;
public var green:Number;
public var blue:Number;
public var lum:Number;
public var alpha:Number;
public var initColor:uint;
public var initRed:Number;
public var initGreen:Number;
public var initBlue:Number;
public var initLum:Number;
public var destColor:uint;
public var destRed:Number;
public var destGreen:Number;
public var destBlue:Number;
public var destLum:Number;
public var colorChanging:Boolean;
function Particle3D(thisColor:uint = 0xFFFFFFFF)
{
this.dest = [];
this.color = thisColor;
this.red = getRed(thisColor);
this.green = getGreen(thisColor);
this.blue = getBlue(thisColor);
this.alpha = getAlpha(thisColor);
this.lum = 0.2126 * this.red + 0.7152 * this.green + 0.0722 * this.blue;
this.colorChanging = false;
this.onScreen = true;
}
public function setColor(thisColor:uint):void
{
this.color = thisColor;
this.red = getRed(thisColor);
this.green = getGreen(thisColor);
this.blue = getBlue(thisColor);
this.alpha = getAlpha(thisColor);
this.lum = 0.2126 * this.red + 0.7152 * this.green + 0.0722 * this.blue;
}
public function getAlpha(c:Number):Number
{
return Number((c >> 24) & 0xFF);
}
public function getRed(c:Number):Number
{
return Number((c >> 16) & 0xFF);
}
public function getGreen(c:Number):Number
{
return Number((c >> 8) & 0xFF);
}
public function getBlue(c:Number):Number
{
return Number(c & 0xFF);
}
}