3D (isometric) fractals @ 16 FPS
http://en.wikipedia.org/wiki/Iterated_function_system
/**
* Copyright yonatan ( http://wonderfl.net/user/yonatan )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/qfJG
*/
// forked from yonatan's Fractals @ 24 FPS
// forked from yonatan's Tweening Sheep (realtime fractal generator)
// http://en.wikipedia.org/wiki/Iterated_function_system
package
{
import flash.display.*;
import flash.events.*;
import flash.filters.*;
import flash.geom.*;
import flash.utils.*;
import flash.text.*;
import flash.ui.Mouse;
import __AS3__.vec.Vector;
import net.hires.debug.Stats;
[SWF(backgroundColor = "0x000000", frameRate = "16")]
public class Main extends Sprite
{
public function Main():void
{
Wonderfl.capture_delay( 30 );
init(stage.stageWidth, stage.stageHeight);
addChild(view);
addChild(new Stats());
addChild( tf = new TextField );
tf.y = 100;
tf.width = stage.stageWidth;
tf.textColor = 0xFFFFFF;
stage.quality = "low";
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
Mouse.cursor = flash.ui.MouseCursor.BUTTON;
stage.addEventListener(MouseEvent.CLICK, onClick);
addEventListener(Event.ENTER_FRAME, onEnter);
}
private function onClick(e:MouseEvent):void
{
change();
}
private var oldTime:Number = 0;
private function adjustToFrameRate():void {
const DAMP:Number = 10;
tf.text = "Iterations/Frame: " + numIterations;
// maintain a constant framerate
var newTime:Number = getTimer();
var iterPerMs:Number = numIterations / (newTime - oldTime);
oldTime = newTime;
numIterations = (numIterations * DAMP + (1000/stage.frameRate) * iterPerMs) / (DAMP+1);
}
private function onEnter(e:Event):void {
for each( var t:FTransform in transforms ) {
t.matrix.appendRotation( 1, new Vector3D(0,1,0), new Vector3D(0,0,0) );
}
draw();
adjustToFrameRate();
}
private var w: int;
private var h: int;
private var mw: int;
private var mh: int;
private const SCREEN_SCALE:Number = 100;
private var view: Bitmap;
private var bmpData: BitmapData;
private var buffer: Vector.<uint>;
private var numIterations:uint = 50000;
private static const NUM_TRANSFORMS:uint = 4;
private var transforms:Vector.<FTransform>;
private var tonedown:ColorTransform;
private var filter:BlurFilter;
private var tf:TextField;
private function init(w: int, h: int):void
{
this.w = w;
mw = w >> 1;
this.h = h;
mh = h >> 1;
bmpData = new BitmapData(w, h, true, 0x00000000);
stage.fullScreenSourceRect = bmpData.rect;
view = new Bitmap(bmpData);
tonedown = new ColorTransform(
.92,.92,.92,0,
-5,-5,-5,255);
filter = new BlurFilter(2.5, 2.5, 1);
// init matrix and color arrays
transforms = new Vector.<FTransform>;
var i:uint;
for( i = 0; i < NUM_TRANSFORMS; i++ ) {
transforms.push( new FTransform );
}
transforms[0].matrix.appendTranslation( 1, 1, 1);
transforms[1].matrix.appendTranslation(-1, -1, 1);
transforms[2].matrix.appendTranslation( 1, -1, -1);
transforms[3].matrix.appendTranslation(-1, 1, -1);
for( i = 0; i < NUM_TRANSFORMS; i++ ) {
transforms[i].matrix.appendScale(.5,.5,.5);
}
//change();
}
private var curx:Number = 0;
private var cury:Number = 0;
private var curz:Number = 0;
private var color:uint = 0xFFFFFF;
private var topleft:Point = new Point(0,0);
private function draw(): void
{
var b: Vector.<uint> = buffer;
var bi: uint; // buf idx
var ti: int; // transform idx
bmpData.lock();
bmpData.fillRect( bmpData.rect, 0 );
b = bmpData.getVector(bmpData.rect);
var screenx:int, screeny:int;
var newx:Number;
var newy:Number;
var xform:FTransform;
var raw:Vector.<Number>;
var rnd:Number;
var zbyte:uint;
for( var i:uint = 0; i < numIterations; i++ ) {
xform = transforms[int(Math.random()*NUM_TRANSFORMS)];
raw = xform.matrix.rawData;
// math courtesy of umhr: http://wonderfl.kayac.com/code/9f8f55a85ed49edb59c1a313063e6abfaf4271e7
newx = (raw[0]*curx + raw[4]*cury + raw[8]*curz) + raw[12];
newy = (raw[1]*curx + raw[5]*cury + raw[9]*curz) + raw[13];
curz = (raw[2]*curx + raw[6]*cury + raw[10]*curz) + raw[14];
curx = newx;
cury = newy;
screenx = curx * SCREEN_SCALE + mw;
screeny = cury * SCREEN_SCALE + mh;
zbyte = curz <= -1 ? 0x80000000 : curz >= 1 ? 0xFF000000 : ((curz + 1) / 2 * 0x7f + 0x80) << 24;
color = ((color & 0xFEFEFE) + (xform.color & 0xFEFEFE)) >>> 1;
if( screenx >= 0 && screenx < w && screeny >= 0 && screeny < h )
{
bi = screeny * w + screenx;
if( (b[bi] & 0xFF000000) < zbyte ) {
//b[bi] = (((color & 0xFEFEFE) + (b[bi] & 0xFEFEFE)) >>> 1) | zbyte;
b[bi] = color | zbyte;
}
}
}
bmpData.setVector(bmpData.rect, b);
bmpData.applyFilter(bmpData, bmpData.rect, topleft, filter);
//bmpData.colorTransform(bmpData.rect, tonedown);
bmpData.unlock();
}
private function change(): void {
for( var i:uint = 0; i < NUM_TRANSFORMS; i++ ) {
var m:Matrix3D = new Matrix3D;
m.appendTranslation( Math.random()*2-1, Math.random()*2-1, Math.random()*2-1 );
m.appendScale( Math.random()/2+0.25, Math.random()/2+0.25, Math.random()/2+0.25 );
m.appendRotation( Math.random()*360, new Vector3D(Math.random(),Math.random(),Math.random()), new Vector3D(0,0,0) );
transforms[i].tweenTo( m, Math.random()*0xFFFFFF | 0x202020 );
}
}
}
}
import flash.geom.Matrix3D;
import gs.TweenMax;
import gs.easing.*;
// ugly tween wrapper
class FTransform{
private var start:Matrix3D;
private var finish:Matrix3D;
public var matrix:Matrix3D;
private var _t:Number;
public var color:uint = Math.random()*0xFFFFFF | 0x202020;
public function FTransform() {
start = new Matrix3D;
finish = new Matrix3D;
matrix = new Matrix3D;
_t = 0;
}
public function tweenTo( dest:Matrix3D, color:uint ):void {
start = matrix;
finish = dest;
t = 0;
TweenMax.to( this, 3, {
ease: Sine.easeInOut,
hexColors:{ color: color },
t: 1
} );
}
public function get t():Number { return _t }
public function set t( value:Number ):void {
_t = value;
matrix = Mtrx3D.myInterpolate( this.start, this.finish, _t );
}
}
class Mtrx3D {
import flash.geom.Matrix3D;
import flash.geom.Vector3D;
public static function myInterpolate(thisMat:Matrix3D,toMat:Matrix3D,percent:Number):Matrix3D{
var v0:Vector3D = thisMat.decompose("quaternion")[1];
var v1:Vector3D = toMat.decompose("quaternion")[1];
var cosOmega:Number = v0.w*v1.w + v0.x*v1.x + v0.y*v1.y + v0.z*v1.z;
if(cosOmega < 0){
v1.x = -v1.x;
v1.y = -v1.y;
v1.z = -v1.z;
v1.w = -v1.w;
cosOmega = -cosOmega;
}
var k0:Number;
var k1:Number;
if(cosOmega > 0.9999){
k0 = 1 - percent;
k1 = percent;
}else{
var sinOmega:Number = Math.sqrt(1 - cosOmega*cosOmega);
var omega:Number = Math.atan2(sinOmega,cosOmega);
var oneOverSinOmega:Number = 1/sinOmega;
k0 = Math.sin((1-percent)*omega)*oneOverSinOmega;
k1 = Math.sin(percent*omega)*oneOverSinOmega;
}
var scale_x:Number = thisMat.decompose("quaternion")[2].x*(1-percent) + toMat.decompose("quaternion")[2].x*percent;
var scale_y:Number = thisMat.decompose("quaternion")[2].y*(1-percent) + toMat.decompose("quaternion")[2].y*percent;
var scale_z:Number = thisMat.decompose("quaternion")[2].z*(1-percent) + toMat.decompose("quaternion")[2].z*percent;
var tx:Number = thisMat.decompose("quaternion")[0].x*(1-percent) + toMat.decompose("quaternion")[0].x*percent;
var ty:Number = thisMat.decompose("quaternion")[0].y*(1-percent) + toMat.decompose("quaternion")[0].y*percent;
var tz:Number = thisMat.decompose("quaternion")[0].z*(1-percent) + toMat.decompose("quaternion")[0].z*percent;
//trace(thisMat.decompose("quaternion")[2].x,toMat.decompose("quaternion")[2].x,scale_x)
var x:Number = v0.x*k0+v1.x*k1;
var y:Number = v0.y*k0+v1.y*k1;
var z:Number = v0.z*k0+v1.z*k1;
var w:Number = v0.w*k0+v1.w*k1;
var _q:Vector.<Number> = new Vector.<Number>(16,true);
_q[0] = (1-2*y*y-2*z*z)*scale_x;
_q[1] = (2*x*y+2*w*z)*scale_x;
_q[2] = (2*x*z-2*w*y)*scale_x;
_q[3] = 0;
_q[4] = 2*x*y-2*w*z*scale_y;
_q[5] = (1-2*x*x-2*z*z)*scale_y;
_q[6] = 2*y*z+2*w*x*scale_y;
_q[7] = 0;
_q[8] = 2*x*z+2*w*y*scale_z;
_q[9] = 2*y*z-2*w*x*scale_z;
_q[10] = (1-2*x*x-2*y*y)*scale_z;
_q[11] = 0;
_q[12] = tx;
_q[13] = ty;
_q[14] = tz;
_q[15] = 1;
//trace(_q)
var v:Vector3D = new Vector3D(v0.x*k0+v1.x*k1,v0.y*k0+v1.y*k1,v0.z*k0+v1.z*k1,v0.w*k0+v1.w*k1);
//var txyz:Vector3D = new Vector3D(tx,ty,tz);
//var m:Matrix3D=new Matrix3D();
//m.recompose(Vector.<Vector3D>([txyz,v,new Vector3D(scale_x,scale_y,scale_z)]),"quaternion");
//trace(m.rawData);
return new Matrix3D(_q);
}
}