In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Triangular kaleidoscope with perlinNoise

FP 10 required !
[SWF(width = 800, height = 780, backgroundColor = 0x101010, frameRate = 30)]

Triangular Kaleidoscope with perlinNoise

using graphics.drawTriangles()-method 
and uv -coordinates for texture mapping
to create a triangular reflections

Petri Leskinen 15.1.2009 Espoo, Finland
http://pixelero.wordpress.com
package 
{
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.display.TriangleCulling; // FP 10 required !
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import flash.text.TextField;
	
	import flash.geom.Point;
	
	//    [SWF(width = 800, height = 780, backgroundColor = 0x101010, frameRate = 30)]
	
	/**
	 * Triangular Kaleidoscope with perlinNoise
	 *
	 * using graphics.drawTriangles()-method 
 	 * and uv -coordinates for texture mapping
	 * to create a triangular reflections
	 *      
	 * Petri Leskinen 15.1.2009 Espoo, Finland
	 * http://pixelero.wordpress.com
	 */
	
	public class TriangularRegular extends Sprite
	{
		
		public var vertices:Vector.<Number> = new Vector.<Number>(),	//	x,y,z -coordinates
			indices:Vector.<int>  = new Vector.<int>(),	//	triangle mesh
			uvtData:Vector.<Number> = new Vector.<Number>(),
			points:Array;
		
		public var bmd:NeonPerlinStripes;
		public var size:Number = 180;
		
		protected var running:Boolean = false, phase:Number = 0.0;
		
		internal var i:int, j:int, tmp:Number;
		
		internal const HALFSQRT3:Number = 0.866025403784438;
		internal const D120:Number = 120.0 / 180.0 * Math.PI;
		
		public function TriangularRegular ():void {
			addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		protected function init(e:Event = null):void {
			
			var po:Object;
			var id:int = 0,xp:Number, yp:Number;
			
			var triangs:Array = [], paths:Array = [], tr:Array;
			var n:int = 3 + stage.stageWidth / size;
			var m:int = 2+stage.stageHeight/size /HALFSQRT3;
			
			var uvIndex:int;
			vertices = new Vector.<Number>();	//	x,y,z -coordinates
			indices = new Vector.<int>();	//	triangle mesh
			uvtData = new Vector.<Number>();
			points = [];
			
                        //    fill the stage (with triangles
			for (j = 0; j != m; j++) {
				paths[j] = [];
				
				yp = size*j *HALFSQRT3;
				uvIndex = ((j & 1) == 0) ? 0 : 2;
				
				for (i = 0; i != n; i++) {
					xp =  (i - 0.5 * (j & 1)) * size ;
					po = { 	x: xp,
						y: yp,
						id: id++,
						uvIndex: uvIndex };
							
					paths[j].push(po);
					points.push(po);
					
					uvIndex= (uvIndex+2)%3; // repeats the serie 2 1 0 2 1 0 2 1 0
				}
				
				if (j != 0) {
					triangulatePaths(paths[j - 1], paths[j], false, triangs);
				}
			}
			
			for each( tr in triangs) indices.push(tr[0].id, tr[1].id, tr[2].id);
			
			bmd = new NeonPerlinStripes(size, size);
			
			stage.addEventListener(MouseEvent.CLICK, toggleAnimation);
			toggleAnimation();
		}
		
		
		
		private function render(e:Event=null):void {
			
			bmd.update();
			
			phase += 0.03;
			
			var uvIndices:Array = [ { u: 0.5+0.5*Math.cos(phase-D120), v:0.5+0.5*Math.sin(phase-D120) },
									{ u: 0.5+0.5*Math.cos(phase), v:0.5+0.5*Math.sin(phase) },
									{ u: 0.5+0.5*Math.cos(phase+D120), v:0.5+0.5*Math.sin(phase+D120)  } ];
									
			uvtData = new Vector.<Number>();
			vertices = new Vector.<Number>();
			
			for each(var po:Object in points) {
				uvtData.push(uvIndices[po.uvIndex].u, uvIndices[po.uvIndex].v);
				vertices.push(po.x, po.y);
			}
			
			
			graphics.clear();
			//	graphics.lineStyle(1.0, 0x808080, 1.0); // uncomment to see the grid
			graphics.beginBitmapFill(
					bmd,
					null, 	//	no matrix
					true	//	= repeat
					);
				
			graphics.drawTriangles(vertices,
							  indices,
							  uvtData,
							  TriangleCulling.NONE);
			
							  
			graphics.endFill();
			
		}
		
		//	generates a triangle strip between two arrays of points
		private function triangulatePaths(path0:Array, path1:Array, closed:Boolean=false, triangles:Array =null):Array {
			if (triangles==null) triangles = [];
			var index0:int = 0,index1:int = 0, dist0:Number, dist1:Number;
			
			var po0:* = path0[index0];
			var po1:* = path1[index1];
			
			//	if 'closed' push the first point as last one as well 
			if (closed && path0.length > 1 && po0!=path0[path0.length-1] ) path0.push(po0);
			if (closed && path1.length > 1 && po1!=path1[path1.length-1] ) path1.push(po1);
			
			//	choose the new triangle by a shorter diagonal
			while (index0 < path0.length-1 && index1 < path1.length-1) {
				dist0 = (tmp = po0.x - path1[index1 + 1].x) * tmp + (tmp = po0.y - path1[index1 + 1].y) * tmp;
				dist1 = (tmp = po1.x - path0[index0 + 1].x) * tmp + (tmp = po1.y - path0[index0 + 1].y) * tmp;
				triangles.push( [po0, po1, (dist0 < dist1) ? po1 = path1[++index1] : po0 = path0[++index0] ]);
			}
			
			//	creates a fan of triangles if the other path's already ended
			while (index0 +1 < path0.length) triangles.push( [po0, po1, po0=path0[++index0]]);
			
			while (index1 +1 < path1.length) triangles.push( [po0, po1, po1=path1[++index1]]);
			
			return triangles;
		}
		
                //    a click will stop animation
		private function toggleAnimation(e:MouseEvent = null):void {
			
			if (running=(!running)) {
				addEventListener(Event.ENTER_FRAME, render);
			} else {
				removeEventListener (Event.ENTER_FRAME, render);
			}
			
		}
		
		
	}
}

//    NeonPerlinStripes:
//    subclass for a modified perlinNoise
import flash.display.BitmapData;
import flash.geom.ColorTransform;
import flash.geom.Point;
import flash.display.BlendMode;
import flash.geom.Vector3D;
import flash.events.Event;
 
class NeonPerlinStripes extends BitmapData {
	
	public var offsets1:Array = [new Point(),new Point(),new Point()];
	private var phaseAngle:Number = 0.0;
	
	private static var edge128:ColorTransform = new ColorTransform(-1,-1,-1,1,255,255,255);
	private static var d120:Number = 120/180*Math.PI;
	
	public function NeonPerlinStripes(w:int, h:int) {
		
		super(w,h,true,0x00);
		
		update();
		
	}
	
	public function update(e:Event=null):void { 
		phaseAngle += 0.03;
		var cs:Number = Math.cos(phaseAngle);
		
		offsets1[0].x += 0.03;
		offsets1[0].y += 0.03;
		offsets1[1].y -= cs*0.4;
		offsets1[2].x -= 0.7;
		
		var scale:Number = 1.0;
		perlinNoise(scale*this.width,scale*this.height,3,13,true,true,1+2+4,false,offsets1);
		
		this.draw(this, 
			null, 
			edge128,
			BlendMode.DARKEN );
		
		var fA:Number = 5.0; // 16.0-0.0*cs;
		var fB:Number = 255.0-128.0*fA; // fA*255+fB = 255
		
		this.draw(this,
				null,
				new ColorTransform(fA,fA,fA,1.0,fB,fB,fB), 
				BlendMode.NORMAL );
		
		
		this.draw(this,
				null,
				new ColorTransform(1.0+cs,
						1.0+Math.cos(phaseAngle+d120),
						1.0+Math.cos(phaseAngle-d120)
						), 
				BlendMode.MULTIPLY );
		
		
	}
}