Commits

Marcus Wendt committed 2725120

added math, physics, physics2d ports

Comments (0)

Files changed (29)

src/field/kit/Sketch.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 12, 2010 */
+package field.kit
+{
+	import flash.display.Sprite;
+	import flash.events.Event;
+	import flash.events.KeyboardEvent;
+
+	[SWF(width="1280", height="760", scale="noscale", backgroundColor="#191919", frameRate="60")]
+	
+	/**
+	 * Base class for all test sketches
+	 */
+	public class Sketch extends Sprite
+	{
+		public function Sketch() {
+			super();
+			addEventListener(Event.ENTER_FRAME, init)
+		}
+		
+		private function init(event:Event):void {
+			trace("init")
+			removeEventListener(Event.ENTER_FRAME, init)
+			setup()
+			
+			stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown)
+			addEventListener(Event.ENTER_FRAME, update)			
+		}
+
+		protected function setup():void {
+			trace("setup")
+		}
+		
+		private function update(event:Event):void {
+			draw()	
+		}
+		
+		protected function draw():void {
+//			trace("draw")
+		}
+		
+		// -- Event Handling ---------------------------------------------------
+		public static var KEY_SPACE:int = 32
+		public static var KEY_D:int = 68
+			
+		public static var KEY_0:int = 48
+		public static var KEY_1:int = 49
+		public static var KEY_2:int = 50
+		public static var KEY_3:int = 51
+		public static var KEY_4:int = 52
+		public static var KEY_5:int = 53
+		public static var KEY_6:int = 54
+		public static var KEY_7:int = 55
+		public static var KEY_8:int = 56
+		public static var KEY_9:int = 57
+		
+		protected var keyCode:int
+		
+		private function keyDown(e:KeyboardEvent):void {
+//			trace("keyDown", e.keyCode)
+			keyCode = e.keyCode
+			keyPressed()
+		}
+		
+		protected function keyPressed():void {}
+	}
+}

src/field/kit/colour/Colour.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 15, 2010 */
+package field.kit.colour
+{
+	/**
+	 * RGB Colour class
+	 */
+	public class Colour
+	{			
+		/** holds the r,g,b data */			
+		protected var rgb:Vector.<uint> = new Vector.<uint>(3, true)
+			
+		/** holds the h,s,v data */
+		protected var hsv:Vector.<uint> = new Vector.<uint>(3, true)
+		
+		public function Colour(_r:uint = 0, _g:uint = 0, _b:uint = 0) {
+			setRGB(_r, _g, _b)
+		}
+		
+		public function set(c:Colour):void {
+			rgb[0] = c.rgb[0]
+			rgb[1] = c.rgb[1]
+			rgb[2] = c.rgb[2]
+				
+			hsv[0] = c.hsv[0]
+			hsv[1] = c.hsv[1]
+			hsv[2] = c.hsv[2]
+		}
+		
+		public function setRGB(_r:uint = 0, _g:uint = 0, _b:uint = 0):void {
+			if(_r < 256) {
+				rgb[0] = _r
+				rgb[1] = _g
+				rgb[2] = _b
+			} else {
+				var _rgb:Array = HexToRGB(_r)
+				rgb[0] = _rgb[0]
+				rgb[1] = _rgb[1]
+				rgb[2] = _rgb[2]
+			}
+			updateHSV()
+		}
+		
+		public function setHSV(_h:uint = 0, _s:uint = 0, _v:uint = 0):void {
+			hsv[0] = _h
+			hsv[1] = _s
+			hsv[2] = _v
+			updateRGB()
+		}
+		
+		/** Converts a RGB colour to a HSV triplet */
+		protected function updateHSV():void {
+			var _hsv:Array = RGBtoHSV(r, g, b)
+			hsv[0] = _hsv[0]
+			hsv[1] = _hsv[1]
+			hsv[2] = _hsv[2]
+		}
+		
+		/** Converts a HSV colour to a RGB triplet */
+		protected function updateRGB():void {
+			var _rgb:Array = HSVtoRGB(h, s, v)
+			rgb[0] = _rgb[0]
+			rgb[1] = _rgb[1]
+			rgb[2] = _rgb[2]
+		}
+		
+		// -- RGB Accessors ----------------------------------------------------
+		public function get r():uint {
+			return rgb[0]
+		}
+		
+		public function set r(value:uint):void {
+			rgb[0] = value
+			updateHSV()
+		}
+
+		public function get g():uint {
+			return rgb[1]
+		}
+		
+		public function set g(value:uint):void {
+			rgb[1] = value
+			updateHSV()
+		}
+		
+		public function get b():uint {
+			return rgb[2]
+		}
+		
+		public function set b(value:uint):void {
+			rgb[2] = value
+			updateHSV()
+		}
+
+		// -- HSV Accessors ----------------------------------------------------
+		public function get h():uint {
+			return hsv[0]
+		}
+		
+		public function set h(value:uint):void {
+			hsv[0] = value % 360
+			updateRGB()
+		}
+		
+		public function get s():uint {
+			return hsv[1]
+		}
+		
+		public function set s(value:uint):void {
+			hsv[1] = value % 100
+			updateRGB()
+		}
+		
+		public function get v():uint {
+			return hsv[2]
+		}
+		
+		public function set v(value:uint):void {
+			hsv[2] = value % 100
+			updateRGB()
+		}
+		
+		// -- Utilities --------------------------------------------------------
+		public function toInt():uint {
+			return (r << 16 | g << 8 | b)
+				
+//			return uint(r) & 0xFF << 16 |
+//				   uint(g) & 0xFF << 8 |
+//				   uint(b) & 0xFF
+		}
+		
+		public function toString():String {
+			return "Colour[r:"+ r +" g:"+ g +" b:"+ b +", h:"+ h +" s:"+ s +" v:" + v +"]"			
+		} 
+		
+		// -- Static conversion methods ----------------------------------------
+		public static function RGBToHex(r:uint, g:uint, b:uint):uint{
+			var hex:uint = (r << 16 | g << 8 | b);
+			return hex;
+		}
+		
+		public static function HexToRGB(hex:uint):Array{
+			var rgb:Array = [];
+			
+			var r:uint = hex >> 16 & 0xFF;
+			var g:uint = hex >> 8 & 0xFF;
+			var b:uint = hex & 0xFF;
+			
+			rgb.push(r, g, b);
+			return rgb;
+		}
+		
+		public static function RGBtoHSV(r:uint, g:uint, b:uint):Array{
+			var max:uint = Math.max(r, g, b);
+			var min:uint = Math.min(r, g, b);
+			
+			var hue:Number = 0;
+			var saturation:Number = 0;
+			var value:Number = 0;
+			
+			var hsv:Array = [];
+			
+			//get Hue
+			if(max == min){
+				hue = 0;
+			}else if(max == r){
+				hue = (60 * (g-b) / (max-min) + 360) % 360;
+			}else if(max == g){
+				hue = (60 * (b-r) / (max-min) + 120);
+			}else if(max == b){
+				hue = (60 * (r-g) / (max-min) + 240);
+			}
+			
+			//get Value
+			value = max;
+			
+			//get Saturation
+			if(max == 0){
+				saturation = 0;
+			}else{
+				saturation = (max - min) / max;
+			}
+			
+			hsv = [Math.round(hue), Math.round(saturation * 100), Math.round(value / 255 * 100)];
+			return hsv;
+			
+		}
+		
+		public static function HSVtoRGB(h:Number, s:Number, v:Number):Array{
+			var r:Number = 0;
+			var g:Number = 0;
+			var b:Number = 0;
+			var rgb:Array = [];
+			
+			var tempS:Number = s / 100;
+			var tempV:Number = v / 100;
+			
+			var hi:int = Math.floor(h/60) % 6;
+			var f:Number = h/60 - Math.floor(h/60);
+			var p:Number = (tempV * (1 - tempS));
+			var q:Number = (tempV * (1 - f * tempS));
+			var t:Number = (tempV * (1 - (1 - f) * tempS));
+			
+			switch(hi){
+				case 0: r = tempV; g = t; b = p; break;
+				case 1: r = q; g = tempV; b = p; break;
+				case 2: r = p; g = tempV; b = t; break;
+				case 3: r = p; g = q; b = tempV; break;
+				case 4: r = t; g = p; b = tempV; break;
+				case 5: r = tempV; g = p; b = q; break;
+			}
+			
+			rgb = [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
+			return rgb;
+		}
+	}
+}

src/field/kit/math/MathUtil.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 13, 2010 */
+package field.kit.math
+{
+	/**
+	 * Various mathematical helper tools
+	 */
+	public final class MathUtil
+	{
+		public function MathUtil() {}
+		
+		public static const EPSILON:Number = Number.MIN_VALUE
+			
+		public static const PI:Number = Math.PI
+		public static const HALF_PI:Number = PI / 2.0
+		public static const TWO_PI:Number = PI * 2.0
+			
+		/** The value 1/PI as a float. */
+		public static const INV_PI:Number = 1.0 / PI
+		
+		/** A value to multiply a degree value by, to convert it to radians. */
+		public static const DEG_TO_RAD:Number = PI / 180.0
+		
+		/** A value to multiply a radian value by, to convert it to degrees. */
+		public static const RAD_TO_DEG:Number = 180.0 / PI
+			
+		public static function randomRange(min:Number, max:Number):Number {
+			return min + (max - min) * Math.random()
+		}
+		
+		public static function flipCoin(chance:Number = 0.5):Boolean {
+			return Math.random() < chance
+		}
+		
+		public static function slerp(current:Number, target:Number, delta:Number):Number {
+			return current * (1 - delta) + target * delta
+		}
+		
+		public static function clamp(value:Number, min:Number, max:Number):Number {
+			if(value < min) return min
+			if(value > max) return max
+			return value
+		}
+	}
+}

src/field/kit/math/Ray2.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 12, 2010 */
+package field.kit.math
+{
+	public class Ray2 extends Vec2
+	{
+		protected var _direction:Vec2 = new Vec2()
+		
+		public function Ray2(x:Number=0, y:Number=0, dirX:Number=0, dirY:Number=0) {
+			super(x, y);
+			direction = new Vec2(dirX, dirY)
+		}
+		
+		public function pointAtDistance(dist:Number):Vec2 {
+			return Vec2(this.add(direction.mulS(dist)))
+		}
+		
+		public function get direction():Vec2 {
+			return _direction;
+		}
+		
+		public function set direction(v:Vec2):void {
+			_direction.set(v).normalizeSelf()
+		}
+	}
+}

src/field/kit/math/Vec.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 12, 2010 */
+package field.kit.math
+{
+	/**
+	 * Base class for all vector classes
+	 */
+	public class Vec
+	{
+		public var x:Number = 0
+		public var y:Number = 0
+		public var z:Number = 0
+		
+		// -- Scalar Operations ------------------------------------------------
+		public function setS(x:Number = 0, y:Number = 0, z:Number = 0):Vec {
+			this.x = x; this.y = y; this.z = z;
+			return this
+		}
+		
+		public function addS(s:Number):Vec { return null }
+		public function addSelfS(s:Number):Vec { return null }
+		 
+		public function subS(s:Number):Vec { return null }
+		public function subSelfS(s:Number):Vec { return null }
+		
+		public function mulS(s:Number):Vec { return null }
+		public function mulSelfS(s:Number):Vec { return null }
+		
+		public function divS(s:Number):Vec { return null }
+		public function divSelfS(s:Number):Vec { return null }
+			
+		// -- Vector Operations ------------------------------------------------
+		public function set(v:Vec):Vec {
+			this.x = v.x; this.y = v.y; this.z = v.z;
+			return this
+		}
+		
+		public function add(v:Vec):Vec { return null }
+		public function addSelf(v:Vec):Vec { return null }
+		 
+		public function sub(v:Vec):Vec { return null }
+		public function subSelf(v:Vec):Vec { return null }
+		
+		public function mul(v:Vec):Vec { return null }
+		public function mulSelf(v:Vec):Vec { return null }
+		
+		public function div(v:Vec):Vec { return null }
+		public function divSelf(v:Vec):Vec { return null }
+		
+		// -- Properties -------------------------------------------------------
+		public function get length():Number {
+			return Math.sqrt(lengthSquared)
+		}
+		
+		public function get lengthSquared():Number { return -1 }
+
+
+		// -- Utilites ---------------------------------------------------------
+		public function dot(v:Vec):Number { return -1 }
+		
+		public function zero():Vec {
+			this.x = 0; this.y = 0; this.z = 0;
+			return this
+		}
+		
+		public function normalize():Vec {
+			var l:Number = length
+			if(l != 0)
+				return divS(l)
+			
+			return null
+		}
+		
+		public function normalizeSelf():Vec {
+			var l:Number = length
+			if(l != 0)
+				divSelfS(l)
+			
+			return this
+		}
+		
+		public function normalizeSelfTo(len:Number):Vec { return null }
+		
+		public function distance(v:Vec):Number {
+			return Math.sqrt(distanceSquared(v))
+		}
+		
+		public function distanceSquared(v:Vec):Number { return -1 }
+		
+		/** 
+		 * returns the angle between the this and another vector
+		 * if both vectors are already normalized, then the normalization step can be skipped 
+		 */ 
+		public function angleBetween(v:Vec, normalize:Boolean=true):Number {
+			var theta:Number = (normalize) ? this.normalize().dot(v.normalize()) : dot(v)
+			return Math.acos(theta)
+		}
+		
+		public function interpolate(target:Vec, delta:Number):Vec  { return null }
+		public function interpolateSelf(target:Vec, delta:Number):Vec { return null }
+		
+		public function randomiseBetween(min:Vec, max:Vec):Vec { return null }
+	}
+}

src/field/kit/math/Vec2.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 12, 2010 */
+package field.kit.math
+{
+	/**
+	 * 2 dimensional vector class
+	 * @author Marcus Wendt
+	 */
+	public class Vec2 extends Vec
+	{
+		public function Vec2(x:Number = 0, y:Number = 0) {	
+			setS(x, y)
+		}
+		
+		// -- Scalar Operations ------------------------------------------------		
+		public override function addS(s:Number):Vec {
+			return new Vec2(x + s, y + s)
+		}
+		
+		public override function addSelfS(s:Number):Vec {
+			this.x += s; this.y += s
+			return this
+		}
+		 
+		public override function subS(s:Number):Vec {
+			return new Vec2(x - s, y - s)
+		}
+		
+		public override function subSelfS(s:Number):Vec {
+			this.x -= s; this.y -= s
+			return this
+		}
+		
+		public override function mulS(s:Number):Vec {
+			return new Vec2(x * s, y * s)
+		}
+		
+		public override function mulSelfS(s:Number):Vec {
+			this.x *= s; this.y *= s
+			return this
+		}
+		
+		public override function divS(s:Number):Vec {
+			return new Vec2(x / s, y / s)
+		}
+		
+		public override function divSelfS(s:Number):Vec {
+			this.x /= s; this.y /= s
+			return this
+		}
+		
+		// -- Vector Operations ------------------------------------------------
+		public override function set(v:Vec):Vec {
+			this.x = v.x; this.y = v.y;
+			return this
+		}
+		
+		public override function add(v:Vec):Vec {
+			return new Vec2(x + v.x, y + v.y)
+		}
+		
+		public override function addSelf(v:Vec):Vec {
+			this.x += v.x; this.y += v.y
+			return this
+		}
+		 
+		public override function sub(v:Vec):Vec {
+			return new Vec2(x - v.x, y - v.y)
+		}
+		
+		public override function subSelf(v:Vec):Vec {
+			this.x -= v.x; this.y -= v.y
+			return this
+		}
+		
+		public override function mul(v:Vec):Vec {
+			return new Vec2(x * v.x, y * v.y)
+		}
+		
+		public override function mulSelf(v:Vec):Vec {
+			this.x *= v.x; this.y *= v.y
+			return this
+		}
+		
+		public override function div(v:Vec):Vec {
+			return new Vec2(x / v.x, y / v.y)
+		}
+		
+		public override function divSelf(v:Vec):Vec {
+			this.x /= v.x; this.y /= v.y
+			return this
+		}
+		 
+		public override function dot(v:Vec):Number {
+			return x * v.x + y * v.y
+		}
+		
+		public override function get lengthSquared():Number {
+			return x * x + y * y
+		}
+				
+		/** Normalizes the vector to the given length. */
+		public override function normalizeSelfTo(len:Number):Vec {
+			var mag:Number = Math.sqrt(x * x + y * y)
+			if(mag > 0) {
+				mag = len / mag
+				x *= mag
+				y *= mag
+			}			
+			return this
+		}
+		
+		public override function distanceSquared(v:Vec):Number {
+			var dx:Number = this.x - v.x
+			var dy:Number = this.y - v.y
+			return dx * dx + dy * dy
+		}
+				
+		public override function interpolate(target:Vec, delta:Number):Vec {
+			var tx:Number = x + (target.x - x) * delta
+			var ty:Number = y + (target.y - y) * delta
+			return new Vec2(tx, ty)
+		}
+		
+		public override function interpolateSelf(target:Vec, delta:Number):Vec {
+			x += (target.x - x) * delta
+			y += (target.y - y) * delta
+			return this
+		}
+		
+		public function angle():Number {
+			return Math.atan2(x, y)
+		}
+		
+		/** returns a copy (new instance) of the vector */
+		public function clone():Vec2 {
+			return new Vec2(x,y)
+		}
+		
+		public function toString():String {
+			return "Vec2["+ x.toFixed(2) +","+ y.toFixed(2) +"]"			
+		} 
+	}
+}

src/field/kit/math/Vec3.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 12, 2010 */
+package field.kit.math
+{
+	import flash.geom.Vector3D;
+
+	/**
+	 * 3 dimensional vector class
+	 * @author Marcus Wendt
+	 */
+	public class Vec3 extends Vec
+	{
+		
+		public function Vec3(x:Number = 0, y:Number = 0, z:Number = 0) {	
+			setS(x, y, z)
+		}
+
+		// -- Scalar Operations ------------------------------------------------
+		public override function addS(s:Number):Vec {
+			return new Vec3(x + s, y + s, z + s)
+		}
+		
+		public override function addSelfS(s:Number):Vec {
+			this.x += s; this.y += s; this.z += s
+			return this
+		}
+		 
+		public override function subS(s:Number):Vec {
+			return new Vec3(x - s, y - s, z - s)
+		}
+		
+		public override function subSelfS(s:Number):Vec {
+			this.x -= s; this.y -= s; this.z -= s;
+			return this
+		}
+		
+		public override function mulS(s:Number):Vec {
+			return new Vec3(x * s, y * s, z * s)
+		}
+		
+		public override function mulSelfS(s:Number):Vec {
+			this.x *= s; this.y *= s; this.z *= s
+			return this
+		}
+		
+		public override function divS(s:Number):Vec {
+			return new Vec3(x / s, y / s, z / s)
+		}
+		
+		public override function divSelfS(s:Number):Vec {
+			this.x /= s; this.y /= s; this.z /= s;
+			return this
+		}
+		
+		// -- Vector Operations ------------------------------------------------
+		public override function add(v:Vec):Vec {
+			return new Vec3(x + v.x, y + v.y, z += v.z)
+		}
+		
+		public override function addSelf(v:Vec):Vec {
+			this.x += v.x; this.y += v.y; this.z += v.z
+			return this
+		}
+		 
+		public override function sub(v:Vec):Vec {
+			return new Vec3(x - v.x, y - v.y, z - v.z)
+		}
+		
+		public override function subSelf(v:Vec):Vec {
+			this.x -= v.x; this.y -= v.y; this.z -= v.z
+			return this
+		}
+		
+		public override function mul(v:Vec):Vec {
+			return new Vec3(x * v.x, y * v.y, z * v.z)
+		}
+		
+		public override function mulSelf(v:Vec):Vec {
+			this.x *= v.x; this.y *= v.y; this.z *= v.z
+			return this
+		}
+		
+		public override function div(v:Vec):Vec {
+			return new Vec3(x / v.x, y / v.y, z / v.z)
+		}
+		
+		public override function divSelf(v:Vec):Vec {
+			this.x /= v.x; this.y /= v.y; this.z /= v.z
+			return this
+		}
+		
+		public override function zero():Vec {
+			this.x = 0; this.y = 0; this.z = 0
+			return this
+		}
+		 
+		public override function dot(v:Vec):Number {
+			return x * v.x + y * v.y + z * v.z
+		}
+		
+		public override function get lengthSquared():Number {
+			return x * x + y * y + z * z
+		}
+		
+		public override function distanceSquared(v:Vec):Number {
+			var dx:Number = this.x - v.x
+			var dy:Number = this.y - v.y
+			var dz:Number = this.z - v.z
+			return dx * dx + dy * dy + dz * dz
+		}
+		
+		/** Normalizes the vector to the given length. */
+		public override function normalizeSelfTo(len:Number):Vec {
+			var mag:Number = Math.sqrt(x * x + y * y + z * z)
+			if(mag > 0) {
+				mag = len / mag
+				x *= mag
+				y *= mag
+				z *= mag
+			}			
+			return this
+		}
+		
+		public override function interpolate(target:Vec, delta:Number):Vec {
+			var tx:Number = x + (target.x - x) * delta
+			var ty:Number = y + (target.y - y) * delta
+			var tz:Number = z + (target.z - z) * delta
+			return new Vec3(tx, ty, tz)
+		}
+		
+		public override function interpolateSelf(target:Vec, delta:Number):Vec {
+			x += (target.x - x) * delta
+			y += (target.y - y) * delta
+			z += (target.z - z) * delta
+			return this
+		}
+		
+		public override function randomiseBetween(min:Vec, max:Vec):Vec {
+			x = min.x + (max.x - min.x) * Math.random()
+			y = min.y + (max.y - min.y) * Math.random()
+			z = min.z + (max.z - min.z) * Math.random()
+			return this
+		}
+		
+		/** returns a copy (new instance) of the vector */
+		public function clone():Vec3 {
+			return new Vec3(x,y,z)
+		}
+		
+		public function toString():String {
+			return "Vec3["+ x.toFixed(2) +","+ y.toFixed(2) +","+ z.toFixed(2) +"]"			
+		} 
+	}
+}

src/field/kit/math/geometry/AABB.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 12, 2010 */
+package field.kit.math.geometry
+{
+	import field.kit.math.Vec;
+	import field.kit.math.Vec3;
+	
+	/**
+	 * An axis-aligned bounding box used among other things for collision detection, physics spaces etc.
+	 */
+	public class AABB extends Vec3
+	{
+		private var _min:Vec3 = new Vec3()
+		private var _max:Vec3 = new Vec3()
+		private var _extent:Vec3 = new Vec3()
+			
+		public function AABB(position:Vec3 = null, dimension:Vec3 = null) {
+			if(position != null)
+				set(position)
+			
+			if(dimension != null)
+				setDimension(dimension)
+		}
+		
+		public function setAABB(box:AABB):void {
+			_min.set(box._min)
+			_max.set(box._max)
+			_extent.set(box._extent)
+		} 
+		
+		public function setDimensionS(width:Number, height:Number, depth:Number):AABB {
+			this.width = width
+			this.height = height
+			this.depth = depth
+			return this
+		}
+		
+		public function setDimension(dimension:Vec3):AABB {
+			this.width = dimension.x
+			this.height = dimension.y
+			this.depth = dimension.z
+			return this
+		}
+		
+		public function get dimension():Vec3 {
+			return Vec3(_extent.mulS(2))
+		}
+		
+		public function get width():Number {
+			return _extent.x * 2
+		}
+		
+		public function set width(value:Number):void {
+			_extent.x = value / 2;
+			updateBounds()
+		}
+		
+		public function get height():Number {
+			return _extent.y * 2;
+		}
+		
+		public function set height(value:Number):void {
+			_extent.y = value / 2;
+			updateBounds()
+		}
+		
+		public function get depth():Number {
+			return _extent.z * 2;
+		}
+		
+		public function set depth(value:Number):void {
+			_extent.z = value / 2;
+			updateBounds()
+		}
+
+		public function get min():Vec {
+			return _min;
+		}
+
+		public function set min(value:Vec):void {
+			_min.set(value);
+			updateDimension();
+		}
+
+		public function get max():Vec {
+			return _max;
+		}
+
+		public function set max(value:Vec):void {
+			_max.set(value);
+			updateDimension();
+		}
+
+		protected function updateDimension():void {
+			_extent.set(_max).subSelf(_min).mulSelfS(0.5)
+			this.set(min).addSelf(_extent)
+		}
+		
+		protected function updateBounds():void {
+			_min.set(this).subSelf(_extent)
+			_max.set(this).addSelf(_extent)
+		}
+		
+		public override function toString():String {
+			return "AABB[position="+ x.toFixed(2) +","+ y.toFixed(2) +","+ z.toFixed(2)
+				+" dimension="+ width.toFixed(2) +","+ height.toFixed(2) +","+ depth.toFixed(2) +"]"			
+		}
+	}
+}

src/field/kit/math/geometry/BSpline.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 12, 2010 */
+package field.kit.math.geometry
+{
+	import field.kit.math.MathUtil;
+	import field.kit.math.Vec;
+	
+	/**
+	 * BSline aka Bezier-Curve class
+	 */
+	public class BSpline extends Spline
+	{
+		protected var s:Number = 1.0 / 6.0
+			
+		public function BSpline() {
+			super();
+		}
+		
+		/**
+		 * <code>point</code> calculates a point on a Bezier curve
+		 */
+		public override function point(time:Number, result:Vec=null):Vec {
+			if(result == null) result = createVec()
+			if(size == 0) return result
+			
+			if(needsUpdate) update()
+			time = checkTime(time)
+				
+			// first point
+			if(!isClosed && time < 0) {
+				result.set(first)
+				
+			// last point
+			} else if(!isClosed && time > 1) {
+				result.set(last)
+				
+			// in between
+			} else {
+				var timeBetween:Number = time / partPercentage
+				var i:int = int(timeBetween)
+				var normalizedTime:Number = timeBetween - i
+					
+				var t:Number = normalizedTime
+				var t2:Number = t * normalizedTime
+				var t3:Number = t2 * normalizedTime
+				i -= 1
+				
+				if(!isClosed && i == -1) {
+					tmp0.set(second).subSelf(first).normalizeSelfTo(MathUtil.EPSILON)
+					tmp1.set(first).subSelf(tmp0)
+				} else {
+					vertex(i, tmp1)
+				}
+				
+				i += 1
+				vertex(i, tmp2)
+				
+				i += 1
+				vertex(i, tmp3)
+				
+				i += 1
+				if(!isClosed && i >= size) {
+					tmp0.set(beforeLast).subSelf(last).normalizeSelfTo(MathUtil.EPSILON)
+					tmp4.set(last).subSelf(tmp0)
+				} else {
+					vertex(i, tmp4)
+				}
+				
+				// calculate point
+				tmp1.mulSelfS(s * (-t3 + 3 * t2 - 3 * t + 1))
+				result.set(tmp1)
+				
+				tmp2.mulSelfS(s * (3 * t3 -6 * t2 + 4))
+				result.addSelf(tmp2)
+				
+				tmp3.mulSelfS(s * (-3 * t3 + 3 * t2 + 3 * t + 1))
+				result.addSelf(tmp3)
+				
+				tmp4.mulSelfS(s* t3)
+				result.addSelf(tmp4)
+			}
+			
+			return result
+		}
+	}
+}

src/field/kit/math/geometry/Circle.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 12, 2010 */
+package field.kit.math.geometry
+{
+	import field.kit.math.Vec;
+	import field.kit.math.Vec2;
+
+	/**
+	 * Defines a mathematical Circle
+	 */
+	public class Circle extends Vec2
+	{
+		public var radius:Number
+		
+		public function Circle(x:Number=0, y:Number=0, r:Number=0) {
+			super(x, y);
+			this.radius = r
+		}
+		
+		public function get diameter():Number {
+			return radius * 2.0;
+		}
+		
+		public function contains(p:Vec):Boolean {
+			return distanceSquared(p) <= radius * radius;
+		}
+		
+		public function point(alpha:Number, result:Vec2=null):Vec2 {
+			if(result == null) result = new Vec2()
+			result.x = this.x + Math.sin(alpha) * radius
+			result.y = this.y + Math.cos(alpha) * radius
+			return result
+		}
+		
+		public function intersects(c:Circle):Boolean {
+			var delta:Vec = c.sub(this)
+			var d:Number = delta.length
+			var r1:Number = radius
+			var r2:Number = c.radius
+			return d <= r1 + r2 && d >= Math.abs(r1 - r2)
+		}
+		
+		public override function toString():String {
+			return "Circle["+ x +","+ y +",radius="+ radius +"]"			
+		}
+	}
+}

src/field/kit/math/geometry/Curve.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 13, 2010 */
+package field.kit.math.geometry
+{
+	import field.kit.math.Vec;
+	import field.kit.math.Vec2;
+
+	/**
+	 * Defines a collection of vertices that make up a curve.
+	 * How this curve is constructed is the job of a subclass. 
+	 */
+	public class Curve
+	{
+		public var vertices:Vector.<Vec> = new Vector.<Vec>
+		public var isClosed:Boolean = false
+			
+		public function Curve() {}
+		
+		public function addVertex(v:Vec):void {
+			vertices.push(v)
+		}
+		
+		public function get size():int {
+			return vertices.length
+		}
+		
+		public function clear():void {
+			vertices.splice(0, Number.MAX_VALUE)
+		}
+		
+		/** sets the given <code>Vec3</code> to the nth vertex of this curve */
+		public function vertex(n:int, result:Vec=null):Vec {
+			if(result == null) result = createVec()
+				
+			// curve is open
+			if(!isClosed) {
+				if(n >= vertices.length) return null
+					
+			// curve is closed
+			} else {
+//				if(n >= vertices.length) n -= vertices.length - 1
+				if(n < 0) n += vertices.length
+				n %= vertices.length
+			}
+			
+			result.set(vertices[n])
+			return result
+		}
+		
+		/** Override this */
+		public function point(time:Number, result:Vec=null):Vec {
+			return null
+		}
+		
+		public function checkTime(t:Number):Number {
+			if(isClosed) {
+				return t % 1.0
+			} else {
+				return t
+			}
+		}
+		/** subclasses could override this to use other dimensions than the default 2 */
+		protected static function createVec():Vec {
+			return new Vec2()
+		}
+	}
+}

src/field/kit/math/geometry/Polyline.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 13, 2010 */
+package field.kit.math.geometry
+{
+	import field.kit.math.Vec;
+
+	/**
+	 * Polyline class
+	 * @author Marcus Wendt
+	 */
+	public class Polyline extends Curve
+	{
+		private var prev:Vec = createVec()
+		private var next:Vec = createVec()
+		private var tmp:Vec = createVec()
+			
+		public function Polyline() {
+			super();
+		}
+		
+		/**
+		 * Note this only returns the closest vertex point not a point inbetween two vertices
+		 */
+		public override function point(time:Number, result:Vec=null):Vec {
+			if(result == null) result = createVec()
+			if(size == 0) return result
+				
+			// first point
+			if(time <= 0 || size <= 1) {
+				result.set(vertices[0])
+				
+			// last point
+			} else if(time >= 1) {
+				result.set(vertices[size-1])
+				
+			// in between
+			} else {
+				var median:Number = time * (size-1)
+				
+				prev.set(vertices[int(Math.floor(median))])
+				next.set(vertices[int(Math.ceil(median))])
+					
+				tmp.set(next).subSelf(prev)
+				result.set(prev).addSelf(tmp)
+			}
+			
+			return result
+		}
+	}
+}

src/field/kit/math/geometry/Spline.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 12, 2010 */
+package field.kit.math.geometry
+{
+	import field.kit.math.MathUtil;
+	import field.kit.math.Vec;
+
+	public class Spline extends Curve
+	{
+		// internal fields used for calculating points on the curve
+		protected var first:Vec = createVec()
+		protected var second:Vec = createVec()
+		protected var beforeLast:Vec = createVec()
+		protected var last:Vec = createVec()
+		
+		protected var tmp0:Vec = createVec()
+		protected var tmp1:Vec = createVec()
+		protected var tmp2:Vec = createVec()
+		protected var tmp3:Vec = createVec()
+		protected var tmp4:Vec = createVec()
+			
+		protected var needsUpdate:Boolean = false
+
+		protected var partPercentage:Number = 0
+			
+		public function Spline() {
+			super();
+		}
+		
+		public override function addVertex(v:Vec):void {
+			super.addVertex(v)
+			needsUpdate = true
+		}
+		
+		public override function clear():void {
+			super.clear()
+			needsUpdate = true
+		}
+		
+		/** has to be called when modifcations to the control vertices were made */
+		public function update():void {
+			needsUpdate = false
+				
+			if(size < 4) return
+				
+			first.set(vertices[0])
+			second.set(vertices[1])
+			beforeLast.set(vertices[vertices.length - 2])
+			last.set(vertices[vertices.length - 1])
+
+			if(isClosed) {
+				partPercentage = 1.0 / size
+			} else {
+				partPercentage = 1.0 / (size - 1)
+			}
+		}
+						
+		/**
+		 * <code>point</code> calculates a point on a Catmull-Rom curve from a
+		 * given time value within the interval [0, 1]. If the value is zero or less,
+		 * the first control point is returned. If the value is one or more, the last
+		 * control point is returned. Using the equation of a Catmull-Rom Curve, the
+		 * point at the interval is calculated and returned.
+		 */
+		public override function point(time:Number, result:Vec=null):Vec {
+			if(result == null) result = createVec()
+			if(size == 0) return result
+				
+			if(needsUpdate) update()
+			time = checkTime(time)
+				
+			// first point
+			if(time < 0) {
+				result.set(first)
+				
+			// last point
+			} else if(time > 1) {
+				result.set(last)
+				
+			// in between
+			} else {
+				var timeBetween:Number = time / partPercentage
+				
+				var i:int = int(timeBetween)				
+				var normalizedTime:Number = timeBetween - i
+				
+				var t:Number = normalizedTime * 0.5
+				var t2:Number = t * normalizedTime
+				var t3:Number = t2 * normalizedTime
+				i -= 1
+				
+				if(!isClosed && i == -1) {
+					tmp0.set(second).subSelf(first).normalizeSelfTo(MathUtil.EPSILON)
+					tmp1.set(first).subSelf(tmp0)
+				} else {
+					vertex(i, tmp1)
+				}
+				
+				i += 1
+				vertex(i, tmp2)
+					
+				i += 1
+				vertex(i, tmp3)
+					
+				i += 1
+				if(!isClosed && i >= size) {
+					tmp0.set(beforeLast).subSelf(last).normalizeSelfTo(MathUtil.EPSILON)
+					tmp4.set(last).subSelf(tmp0)
+				} else {
+					vertex(i, tmp4)
+				}
+				
+				// calculate point
+				tmp1.mulSelfS(-t3 + 2 * t2 - t)
+				result.set(tmp1)
+				
+				tmp2.mulSelfS(3 * t3 - 5 * t2 + 1)
+				result.addSelf(tmp2)
+				
+				tmp3.mulSelfS(-3 * t3 + 4 * t2 + t)
+				result.addSelf(tmp3)
+				
+				tmp4.mulSelfS(t3 - t2)
+				result.addSelf(tmp4)
+			}
+			
+			return result
+		}
+	}
+}

src/field/kit/physics/Behavioural.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 11, 2010 */
+package field.kit.physics
+{
+	public class Behavioural
+	{
+		public function Behavioural() {}
+		
+		// -- Behaviours -------------------------------------------------------
+		protected var behaviours:Vector.<Function>
+		
+		public function addBehaviour(e:Function):void {
+			if(behaviours == null) behaviours = new Vector.<Function>()
+			behaviours.push(e)
+		}
+		
+		public function removeBehaviour(e:Function):void {
+			if(behaviours == null) return
+			var i:Number = behaviours.indexOf(e)
+			if(i != -1)
+				behaviours.splice(i, 1)
+		}
+		
+		// -- Constraints ------------------------------------------------------
+		protected var constraints:Vector.<Function>
+		
+		public function addConstraint(e:Function):void {
+			if(constraints == null) constraints = new Vector.<Function>()
+			constraints.push(e)
+		}
+		
+		public function removeConstraint(e:Function):void {
+			if(constraints == null) return
+			var i:Number = constraints.indexOf(e)
+			if(i != -1)
+				constraints.splice(i, 1)
+		}
+	}
+}

src/field/kit/physics/Emitter.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 11, 2010 */
+package field.kit.physics
+{
+	import field.kit.math.Vec;
+	import field.kit.math.Vec3;
+
+	/**
+	 * Instantiates particles and adds it to the physics system
+	 */
+	public class Emitter extends Behavioural
+	{
+		public var position:Vec
+			
+		public var rate:Number = 1
+		public var interval:Number = 1000
+		public var max:Number = 100
+
+		protected var physics:Physics
+		protected var time:Number
+		
+		public function Emitter(physics:Physics) {
+			this.physics = physics
+			position = new Vec3()
+		}
+		
+		public function update(dt:Number):void {
+			time += dt
+			if(time < interval) return
+			time = 0
+				
+			// emit particles
+			var j:int = 0
+			while(j < rate && physics.numParticles < max) {
+				emit(position)
+				j += 1
+			}
+		}
+		
+		/** emits a single particle and applies the emitter behaviours */
+		public function emit(position:Vec = null):Particle {
+			var p:Particle = createParticle()
+			
+			// set particle to start at the emitters position
+			p.setPosition(position == null ? this.position : position) 
+			
+			// add particle to physics
+			physics.addParticle(p)
+			
+			// apply behaviours
+			applyBehaviours(p)
+			applyConstraints(p)
+			
+			return p
+		}
+			
+		/** creates a new particle object from the parameterized type */
+		public function createParticle():Particle {
+			return new Particle()
+		}
+		
+		// -- Behaviours -------------------------------------------------------
+		/**
+		 * Applies all assigned behaviours to this particle
+		 */
+		protected function applyBehaviours(p:Particle):void {
+			if(behaviours == null) return
+			var l:int = behaviours.length
+			for(var i:int=0; i < l; i++) {
+				behaviours[i](p)
+			}
+		}
+		
+		// -- Constraints ------------------------------------------------------
+		/**
+		 * Applies all assigned constraints to this particle
+		 */
+		protected function applyConstraints(p:Particle):void {
+			if(constraints == null) return
+			var l:int = constraints.length
+			for(var i:int=0; i < l; i++) {
+				constraints[i](p)
+			}
+		}
+	}
+}

src/field/kit/physics/Particle.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 11, 2010 */
+package field.kit.physics
+{
+	import field.kit.math.*;
+
+	/**
+	 * 3D Verlet Particle class with support for multiple behaviours
+	 * 
+	 * TODO state handling, colour integration
+	 */
+	public class Particle extends Behavioural
+	{
+		public var age:Number = 0
+	
+		/** the radial size of this particle in the physics space */
+		public var size:Number = 1
+		
+		/** mass of this particle */
+		protected var _weight:Number
+		
+		protected var _invWeight:Number
+		
+		/** Whether this particle can be moved */ 
+		public var isLocked:Boolean = false
+			
+		/** Position in the physical space */
+		public var position:Vec
+		
+		/** Position in the previous frame */
+		public var prev:Vec
+
+		/** internal use */
+		protected var tmp:Vec
+		
+		/** Steering force */
+		public var force:Vec
+		
+		/** Air resistance or fluid resistance, force opposed to the relative motion of this particle */
+		public var drag:Number = 0.03
+
+		public function Particle() {
+			position = new Vec3()
+			prev = new Vec3()
+			tmp = new Vec3()
+			force = new Vec3()
+			weight = 1
+		}
+
+		// -- Update -----------------------------------------------------------
+		public function update(dt:Number):void {
+			updateState(dt)
+			if(isLocked) return
+			updatePosition()
+			applyBehaviours()
+			applyConstraints()
+		}
+		
+		public function lock():void {
+			isLocked = true
+		}
+		
+		public function unlock():void {
+			isLocked = false
+		}
+		
+		// -- State Machine ----------------------------------------------------
+		protected function updateState(dt:Number):void {
+			age += dt
+		}
+		
+		// -- Verlet Integration -----------------------------------------------
+		protected function updatePosition():void {
+			tmp.set(position)
+			
+			position.x += (position.x - prev.x) + force.x
+			position.y += (position.y - prev.y) + force.y
+			position.z += (position.z - prev.z) + force.z
+			
+			prev.set(tmp)
+			scaleVelocity(1.0 - drag)
+			force.zero()
+		}
+		
+		/** sets the velocity of this particle to zero */
+		public function clearVelocity():void {
+			prev.set(position)
+		}
+		
+		public function scaleVelocity(s:Number):void {
+			prev.interpolate(position, 1.0 - s)
+		}
+		
+		public function setPosition(v:Vec):void {
+			position.set(v)
+			clearVelocity()
+		}
+			
+		// -- Behaviours -------------------------------------------------------
+		/**
+		 * Applies all assigned behaviours to this particle
+		 */
+		public function applyBehaviours():void {
+			if(behaviours == null) return
+			var l:int = behaviours.length
+			for(var i:int=0; i < l; i++) {
+				behaviours[i](this)
+			}
+		}
+		
+		// -- Constraints ------------------------------------------------------
+		/**
+		 * Applies all assigned constraints to this particle
+		 */
+		public function applyConstraints():void {
+			if(constraints == null) return
+			var l:int = constraints.length
+			for(var i:int=0; i < l; i++) {
+				constraints[i](this)
+			}
+		}
+
+		public function get weight():Number { return _weight }
+
+		public function set weight(value:Number):void {
+			_weight = value;
+			_invWeight = 1.0 / weight
+		}
+		
+		public function get invWeight():Number { return _invWeight }
+
+		public function toString():String {
+			return "Particle[position="+ position +",size="+ size +"]"			
+		} 
+	}
+}

src/field/kit/physics/Physics.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 11, 2010 */
+package field.kit.physics
+{
+	import field.kit.math.Vec;
+	import field.kit.math.Vec3;
+
+	/**
+	 * Manager class to combine Particles, String, Behaviours and Constraints into one simulation
+	 * 
+	 * TODO neighbour search
+	 */
+	public class Physics extends Behavioural
+	{
+		public var space:Space;
+		public var emitter:Emitter;
+		public var particles:Vector.<Particle> = new Vector.<Particle>();
+		
+		public function Physics() {
+			super()
+			space = new Space()
+			space.setDimensionS(1000, 1000, 1000)
+			emitter = new Emitter(this)
+		}
+		
+		public function update(dt:Number):void {
+			if(emitter != null)
+				emitter.update(dt)
+					
+			updateParticles(dt)
+			updateSprings()
+		}
+		
+		public function clear():void {
+			particles.splice(0, Number.MAX_VALUE)
+			
+			if(behaviours != null)
+				behaviours.splice(0, Number.MAX_VALUE)
+			
+			if(constraints != null)
+				constraints.splice(0, Number.MAX_VALUE)
+			
+			if(springs != null)
+				springs.splice(0, Number.MAX_VALUE)
+		}
+		
+		public function get numParticles():int {
+			return particles.length;
+		}
+		
+		public function get numSprings():int {
+			return (springs == null) ? 0 : springs.length
+		}
+		
+		// -- Particles --------------------------------------------------------
+		protected function updateParticles(dt:Number):void {
+			var l:int = particles.length
+			for(var i:int =0; i < l; i++) {
+				particles[i].update(dt)
+			}
+		}
+		
+		/**
+		 * Creates a new particle using the emitter
+		 */
+		public function createParticle(position:Vec = null):Particle {
+			if(emitter == null) return null
+			return emitter.emit(position)
+		}
+		
+		/**
+		 * Adds a new particle to this flock
+		 */
+		public function addParticle(p:Particle):void {
+			particles.push(p)
+				
+			// add behaviours & constraints  to particle
+			if(behaviours != null)
+				for(var i:int=0; i<behaviours.length; i++)
+					p.addBehaviour(behaviours[i])
+			
+			if(constraints != null)
+				for(var j:int=0; j<constraints.length; j++)
+					p.addConstraint(constraints[j])
+		}
+		
+		/**
+		 * Removes a particle from this flock
+		 */
+		public function removeParticle(p:Particle):void {
+			var k:Number = particles.indexOf(p)
+			if(k != -1)
+				particles.splice(k, 1)
+			
+			// remove behaviours & constraints from particle
+			if(behaviours != null)
+				for(var i:int=0; i<behaviours.length; i++)
+					p.removeBehaviour(behaviours[i])
+			
+			if(constraints != null)
+				for(var j:int=0; j<constraints.length; j++)
+					p.removeConstraint(constraints[j])
+		}
+		
+		// -- Behaviours -------------------------------------------------------
+		public override function addBehaviour(e:Function):void {
+			super.addBehaviour(e)
+			// add new behaviour to all particles
+			for(var i:int=0; i<particles.length; i++)
+				particles[i].addBehaviour(e)
+		}
+		
+		public override function removeBehaviour(e:Function):void {
+			super.removeBehaviour(e)
+			// remove behaviour from all particles
+			for(var i:int=0; i<particles.length; i++)
+				particles[i].removeBehaviour(e)
+		}
+		
+		
+		// -- Constraints ------------------------------------------------------
+		public override function addConstraint(e:Function):void {
+			super.addConstraint(e)
+			// add new constraint to all particles
+			for(var i:int=0; i<particles.length; i++)
+				particles[i].addConstraint(e)
+		}
+		
+		public override function removeConstraint(e:Function):void {
+			super.removeConstraint(e)
+			// remove constraint from all particles
+			for(var i:int=0; i<particles.length; i++)
+				particles[i].removeConstraint(e)
+		}
+		
+		// -- Springs ----------------------------------------------------------
+		public var springs:Vector.<Spring>
+		
+		public function addSpring(e:Spring):void {
+			if(springs == null) springs = new Vector.<Spring>()
+			springs.push(e)
+		}
+		
+		public function removeSpring(e:Spring):void {
+			if(springs == null) return
+	
+			var i:Number = springs.indexOf(e)
+			if(i != -1)
+				springs.splice(i, 1)
+		}
+		
+		/**
+		 * Updates all spring connections based on new particle positions
+		 */
+		protected function updateSprings():void {
+			if(springs == null) return
+				
+			var l:int = springs.length
+			for(var i:int =0; i < l; i++) {
+				springs[i].update(true)
+			}
+		}
+	}
+}

src/field/kit/physics/Space.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 11, 2010 */
+package field.kit.physics
+{
+	import field.kit.math.geometry.AABB;
+
+	/**
+	 * Defines the 3D space a physics simulation works in
+	 * 
+	 * TODO add optimisd methods to find particles at arbitrary positions e.g. Octree, Quadtree, Spatial Hashing
+	 */
+	public class Space extends AABB
+	{
+		public function Space() {}
+		
+		public function setSpace(s:Space):void {
+			setAABB(s)
+		}
+	}
+}

src/field/kit/physics/Spring.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 11, 2010 */
+package field.kit.physics
+{
+	import field.kit.math.MathUtil;
+	import field.kit.math.Vec;
+	import field.kit.math.Vec2;
+	import field.kit.math.Vec3;
+
+	public class Spring
+	{
+		public var a:Particle
+		public var b:Particle
+		
+		/** Spring rest length to which it always wants to return too */
+		public var restLength:Number
+		
+		/** Spring strength, possible value range depends on engine configuration */
+		public var strength:Number
+		
+		/** Flag, if either particle is locked in space */
+		public var isALocked:Boolean = false
+		public var isBLocked:Boolean = false
+		
+		// internal
+		protected var delta:Vec
+		protected var tmp:Vec
+
+		public function Spring(a:Particle=null, b:Particle=null,
+							   strength:Number = 0.5,
+							   restLength:Number = Number.NaN) {
+			this.a = a
+			this.b = b
+			this.strength = strength
+				
+			if(isNaN(restLength))
+				this.restLength = a.position.distance(b.position) + MathUtil.EPSILON
+				
+			// create temp vectors
+			delta = new Vec3
+			tmp = new Vec3
+		}		
+		
+		/**
+		 * Updates both a & b's positions taking their weight and the springs strength and restlength into account
+		 */
+		public function update(applyConstraints:Boolean):void {				
+			delta.set(b.position).subSelf(a.position)
+			var dist:Number = delta.length
+				
+			if(dist == 0) {
+				trace("WARNING: distance between two spring particles is 0!", a.position, b.position)
+//				return
+				dist = 0.1
+			}
+			
+			var normDistStrength:Number = (dist - restLength) / (dist * (a.invWeight + b.invWeight)) * strength
+			
+			if(!a.isLocked && !isALocked) {
+				tmp.set(delta).mulSelfS(normDistStrength * a.invWeight)
+				a.position.addSelf(tmp)
+				if(applyConstraints)
+					a.applyConstraints()
+			}
+			
+			if(!b.isLocked && !isBLocked) {
+				tmp.set(delta).mulSelfS(-normDistStrength * b.invWeight)
+				b.position.addSelf(tmp)
+				if(applyConstraints)
+					b.applyConstraints()
+			}
+		}
+	}
+}

src/field/kit/physics2d/Emitter2D.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 14, 2010 */
+package field.kit.physics2d
+{
+	import field.kit.math.Vec2;
+	import field.kit.physics.Emitter;
+	import field.kit.physics.Particle;
+	import field.kit.physics.Physics;
+	
+	public class Emitter2D extends Emitter
+	{
+		public function Emitter2D(physics:Physics) {
+			super(physics)
+			position = new Vec2()
+		}
+		
+		/** creates a new particle object from the parameterized type */
+		public override function createParticle():Particle {
+			return new Particle2D()
+		}
+	}
+}

src/field/kit/physics2d/Particle2D.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 11, 2010 */
+package field.kit.physics2d
+{
+	import field.kit.math.Vec2;
+	import field.kit.physics.Particle;
+	
+	/**
+	 * 2D Verlet Particle class
+	 */
+	public class Particle2D extends Particle
+	{
+		public function Particle2D() {
+			super();
+			position = new Vec2()
+			prev = new Vec2()
+			tmp = new Vec2()
+			force = new Vec2()
+		}
+		
+		protected override function updatePosition():void {
+			tmp.set(position)
+			
+			position.x += (position.x - prev.x) + force.x
+			position.y += (position.y - prev.y) + force.y
+			
+			prev.set(tmp)
+			scaleVelocity(1.0 - drag)
+			force.zero()
+		}
+
+	}
+}

src/field/kit/physics2d/Physics2D.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 14, 2010 */
+package field.kit.physics2d
+{
+	import field.kit.physics.Physics;
+	
+	public class Physics2D extends Physics
+	{
+		public function Physics2D() {
+			super();
+			emitter = new Emitter2D(this);
+		}
+	}
+}

src/field/kit/physics2d/Spring2D.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 14, 2010 */
+package field.kit.physics2d
+{
+	import field.kit.math.Vec2;
+	import field.kit.physics.Particle;
+	import field.kit.physics.Spring;
+	
+	public class Spring2D extends Spring
+	{
+		public function Spring2D(a:Particle=null, b:Particle=null, 
+								 strength:Number=0.5, restLength:Number=Number.NaN) {
+			super(a, b, strength, restLength);
+			
+			delta = new Vec2()
+			tmp = new Vec2()
+		}
+	}
+}

src/field/kit/test/math/geometry/ClosedCurveTest.as

+/*                                                                            *\
+**           _____  __  _____  __     ____                                    **
+**          / ___/ / / /____/ / /    /    \    FieldKit                       **
+**         / ___/ /_/ /____/ / /__  /  /  /    (c) 2010, FIELD                **
+**        /_/        /____/ /____/ /_____/     http://www.field.io            **
+\*                                                                            */
+/* created April 13, 2010 */
+package field.kit.test.math.geometry
+{
+	import field.kit.Sketch;