Explorar el Código

Updated builds.

Mr.doob hace 12 años
padre
commit
3b43428283
Se han modificado 2 ficheros con 1188 adiciones y 1225 borrados
  1. 1184 1211
      build/three.js
  2. 4 14
      build/three.min.js

+ 1184 - 1211
build/three.js

@@ -27653,10 +27653,9 @@ THREE.typeface_js = self._typeface_js;
  * .getLength()
  * .getLength()
  * .updateArcLengths()
  * .updateArcLengths()
  *
  *
- * This file contains following classes:
+ * This following classes subclasses THREE.Curve:
  *
  *
  * -- 2d classes --
  * -- 2d classes --
- * THREE.Curve
  * THREE.LineCurve
  * THREE.LineCurve
  * THREE.QuadraticBezierCurve
  * THREE.QuadraticBezierCurve
  * THREE.CubicBezierCurve
  * THREE.CubicBezierCurve
@@ -27907,1960 +27906,1934 @@ THREE.Curve.prototype.getTangentAt = function ( u ) {
 
 
 };
 };
 
 
+
+
+
+
 /**************************************************************
 /**************************************************************
- *	Line
+ *	Utils
  **************************************************************/
  **************************************************************/
 
 
-THREE.LineCurve = function ( v1, v2 ) {
+THREE.Curve.Utils = {
 
 
-	this.v1 = v1;
-	this.v2 = v2;
+	tangentQuadraticBezier: function ( t, p0, p1, p2 ) {
 
 
-};
+		return 2 * ( 1 - t ) * ( p1 - p0 ) + 2 * t * ( p2 - p1 );
 
 
-THREE.LineCurve.prototype = Object.create( THREE.Curve.prototype );
+	},
 
 
-THREE.LineCurve.prototype.getPoint = function ( t ) {
+	// Puay Bing, thanks for helping with this derivative!
 
 
-	var point = this.v2.clone().sub(this.v1);
-	point.multiplyScalar( t ).add( this.v1 );
+	tangentCubicBezier: function (t, p0, p1, p2, p3 ) {
 
 
-	return point;
+		return -3 * p0 * (1 - t) * (1 - t)  +
+			3 * p1 * (1 - t) * (1-t) - 6 *t *p1 * (1-t) +
+			6 * t *  p2 * (1-t) - 3 * t * t * p2 +
+			3 * t * t * p3;
+	},
 
 
-};
 
 
-// Line curve is linear, so we can overwrite default getPointAt
+	tangentSpline: function ( t, p0, p1, p2, p3 ) {
 
 
-THREE.LineCurve.prototype.getPointAt = function ( u ) {
+		// To check if my formulas are correct
 
 
-	return this.getPoint( u );
+		var h00 = 6 * t * t - 6 * t; 	// derived from 2t^3 − 3t^2 + 1
+		var h10 = 3 * t * t - 4 * t + 1; // t^3 − 2t^2 + t
+		var h01 = -6 * t * t + 6 * t; 	// − 2t3 + 3t2
+		var h11 = 3 * t * t - 2 * t;	// t3 − t2
 
 
-};
+		return h00 + h10 + h01 + h11;
 
 
-THREE.LineCurve.prototype.getTangent = function( t ) {
+	},
 
 
-	var tangent = this.v2.clone().sub(this.v1);
+	// Catmull-Rom
 
 
-	return tangent.normalize();
+	interpolate: function( p0, p1, p2, p3, t ) {
+
+		var v0 = ( p2 - p0 ) * 0.5;
+		var v1 = ( p3 - p1 ) * 0.5;
+		var t2 = t * t;
+		var t3 = t * t2;
+		return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
+
+	}
 
 
 };
 };
 
 
+
+// TODO: Transformation for Curves?
+
 /**************************************************************
 /**************************************************************
- *	Quadratic Bezier curve
+ *	3D Curves
  **************************************************************/
  **************************************************************/
 
 
+// A Factory method for creating new curve subclasses
 
 
-THREE.QuadraticBezierCurve = function ( v0, v1, v2 ) {
+THREE.Curve.create = function ( constructor, getPointFunc ) {
 
 
-	this.v0 = v0;
-	this.v1 = v1;
-	this.v2 = v2;
+	constructor.prototype = Object.create( THREE.Curve.prototype );
+	constructor.prototype.getPoint = getPointFunc;
+
+	return constructor;
 
 
 };
 };
+/**
+ * @author zz85 / http://www.lab4games.net/zz85/blog
+ *
+ **/
 
 
-THREE.QuadraticBezierCurve.prototype = Object.create( THREE.Curve.prototype );
+/**************************************************************
+ *	Curved Path - a curve path is simply a array of connected
+ *  curves, but retains the api of a curve
+ **************************************************************/
 
 
+THREE.CurvePath = function () {
 
 
-THREE.QuadraticBezierCurve.prototype.getPoint = function ( t ) {
+	this.curves = [];
+	this.bends = [];
+	
+	this.autoClose = false; // Automatically closes the path
+};
 
 
-	var tx, ty;
+THREE.CurvePath.prototype = Object.create( THREE.Curve.prototype );
 
 
-	tx = THREE.Shape.Utils.b2( t, this.v0.x, this.v1.x, this.v2.x );
-	ty = THREE.Shape.Utils.b2( t, this.v0.y, this.v1.y, this.v2.y );
+THREE.CurvePath.prototype.add = function ( curve ) {
 
 
-	return new THREE.Vector2( tx, ty );
+	this.curves.push( curve );
 
 
 };
 };
 
 
+THREE.CurvePath.prototype.checkConnection = function() {
+	// TODO
+	// If the ending of curve is not connected to the starting
+	// or the next curve, then, this is not a real path
+};
 
 
-THREE.QuadraticBezierCurve.prototype.getTangent = function( t ) {
-
-	var tx, ty;
+THREE.CurvePath.prototype.closePath = function() {
+	// TODO Test
+	// and verify for vector3 (needs to implement equals)
+	// Add a line curve if start and end of lines are not connected
+	var startPoint = this.curves[0].getPoint(0);
+	var endPoint = this.curves[this.curves.length-1].getPoint(1);
+	
+	if (!startPoint.equals(endPoint)) {
+		this.curves.push( new THREE.LineCurve(endPoint, startPoint) );
+	}
+	
+};
 
 
-	tx = THREE.Curve.Utils.tangentQuadraticBezier( t, this.v0.x, this.v1.x, this.v2.x );
-	ty = THREE.Curve.Utils.tangentQuadraticBezier( t, this.v0.y, this.v1.y, this.v2.y );
+// To get accurate point with reference to
+// entire path distance at time t,
+// following has to be done:
 
 
-	// returns unit vector
+// 1. Length of each sub path have to be known
+// 2. Locate and identify type of curve
+// 3. Get t for the curve
+// 4. Return curve.getPointAt(t')
 
 
-	var tangent = new THREE.Vector2( tx, ty );
-	tangent.normalize();
+THREE.CurvePath.prototype.getPoint = function( t ) {
 
 
-	return tangent;
+	var d = t * this.getLength();
+	var curveLengths = this.getCurveLengths();
+	var i = 0, diff, curve;
 
 
-};
+	// To think about boundaries points.
 
 
+	while ( i < curveLengths.length ) {
 
 
-/**************************************************************
- *	Cubic Bezier curve
- **************************************************************/
+		if ( curveLengths[ i ] >= d ) {
 
 
-THREE.CubicBezierCurve = function ( v0, v1, v2, v3 ) {
+			diff = curveLengths[ i ] - d;
+			curve = this.curves[ i ];
 
 
-	this.v0 = v0;
-	this.v1 = v1;
-	this.v2 = v2;
-	this.v3 = v3;
+			var u = 1 - diff / curve.getLength();
 
 
-};
+			return curve.getPointAt( u );
 
 
-THREE.CubicBezierCurve.prototype = Object.create( THREE.Curve.prototype );
+			break;
+		}
 
 
-THREE.CubicBezierCurve.prototype.getPoint = function ( t ) {
+		i ++;
 
 
-	var tx, ty;
+	}
 
 
-	tx = THREE.Shape.Utils.b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
-	ty = THREE.Shape.Utils.b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
+	return null;
 
 
-	return new THREE.Vector2( tx, ty );
+	// loop where sum != 0, sum > d , sum+1 <d
 
 
 };
 };
 
 
-THREE.CubicBezierCurve.prototype.getTangent = function( t ) {
+/*
+THREE.CurvePath.prototype.getTangent = function( t ) {
+};*/
 
 
-	var tx, ty;
 
 
-	tx = THREE.Curve.Utils.tangentCubicBezier( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
-	ty = THREE.Curve.Utils.tangentCubicBezier( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
+// We cannot use the default THREE.Curve getPoint() with getLength() because in
+// THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
+// getPoint() depends on getLength
 
 
-	var tangent = new THREE.Vector2( tx, ty );
-	tangent.normalize();
+THREE.CurvePath.prototype.getLength = function() {
 
 
-	return tangent;
+	var lens = this.getCurveLengths();
+	return lens[ lens.length - 1 ];
 
 
 };
 };
 
 
+// Compute lengths and cache them
+// We cannot overwrite getLengths() because UtoT mapping uses it.
 
 
-/**************************************************************
- *	Spline curve
- **************************************************************/
+THREE.CurvePath.prototype.getCurveLengths = function() {
 
 
-THREE.SplineCurve = function ( points /* array of Vector2 */ ) {
+	// We use cache values if curves and cache array are same length
 
 
-	this.points = (points == undefined) ? [] : points;
+	if ( this.cacheLengths && this.cacheLengths.length == this.curves.length ) {
 
 
-};
+		return this.cacheLengths;
 
 
-THREE.SplineCurve.prototype = Object.create( THREE.Curve.prototype );
+	};
 
 
-THREE.SplineCurve.prototype.getPoint = function ( t ) {
+	// Get length of subsurve
+	// Push sums into cached array
 
 
-	var v = new THREE.Vector2();
-	var c = [];
-	var points = this.points, point, intPoint, weight;
-	point = ( points.length - 1 ) * t;
+	var lengths = [], sums = 0;
+	var i, il = this.curves.length;
 
 
-	intPoint = Math.floor( point );
-	weight = point - intPoint;
+	for ( i = 0; i < il; i ++ ) {
 
 
-	c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
-	c[ 1 ] = intPoint;
-	c[ 2 ] = intPoint  > points.length - 2 ? points.length -1 : intPoint + 1;
-	c[ 3 ] = intPoint  > points.length - 3 ? points.length -1 : intPoint + 2;
+		sums += this.curves[ i ].getLength();
+		lengths.push( sums );
 
 
-	v.x = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight );
-	v.y = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight );
+	}
 
 
-	return v;
+	this.cacheLengths = lengths;
+
+	return lengths;
 
 
 };
 };
 
 
-/**************************************************************
- *	Ellipse curve
- **************************************************************/
 
 
-THREE.EllipseCurve = function ( aX, aY, xRadius, yRadius,
-							aStartAngle, aEndAngle,
-							aClockwise ) {
 
 
-	this.aX = aX;
-	this.aY = aY;
+// Returns min and max coordinates, as well as centroid
 
 
-	this.xRadius = xRadius;
-	this.yRadius = yRadius;
+THREE.CurvePath.prototype.getBoundingBox = function () {
 
 
-	this.aStartAngle = aStartAngle;
-	this.aEndAngle = aEndAngle;
+	var points = this.getPoints();
 
 
-	this.aClockwise = aClockwise;
+	var maxX, maxY, maxZ;
+	var minX, minY, minZ;
 
 
-};
+	maxX = maxY = Number.NEGATIVE_INFINITY;
+	minX = minY = Number.POSITIVE_INFINITY;
 
 
-THREE.EllipseCurve.prototype = Object.create( THREE.Curve.prototype );
+	var p, i, il, sum;
 
 
-THREE.EllipseCurve.prototype.getPoint = function ( t ) {
+	var v3 = points[0] instanceof THREE.Vector3;
 
 
-	var deltaAngle = this.aEndAngle - this.aStartAngle;
+	sum = v3 ? new THREE.Vector3() : new THREE.Vector2();
 
 
-	if ( !this.aClockwise ) {
+	for ( i = 0, il = points.length; i < il; i ++ ) {
 
 
-		t = 1 - t;
+		p = points[ i ];
 
 
-	}
+		if ( p.x > maxX ) maxX = p.x;
+		else if ( p.x < minX ) minX = p.x;
 
 
-	var angle = this.aStartAngle + t * deltaAngle;
+		if ( p.y > maxY ) maxY = p.y;
+		else if ( p.y < minY ) minY = p.y;
 
 
-	var tx = this.aX + this.xRadius * Math.cos( angle );
-	var ty = this.aY + this.yRadius * Math.sin( angle );
+		if ( v3 ) {
 
 
-	return new THREE.Vector2( tx, ty );
+			if ( p.z > maxZ ) maxZ = p.z;
+			else if ( p.z < minZ ) minZ = p.z;
 
 
-};
+		}
 
 
-/**************************************************************
- *	Arc curve
- **************************************************************/
+		sum.add( p );
 
 
-THREE.ArcCurve = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
+	}
 
 
-	THREE.EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
-};
+	var ret = {
 
 
-THREE.ArcCurve.prototype = Object.create( THREE.EllipseCurve.prototype );
+		minX: minX,
+		minY: minY,
+		maxX: maxX,
+		maxY: maxY,
+		centroid: sum.divideScalar( il )
 
 
+	};
 
 
-/**************************************************************
- *	Utils
- **************************************************************/
+	if ( v3 ) {
 
 
-THREE.Curve.Utils = {
+		ret.maxZ = maxZ;
+		ret.minZ = minZ;
 
 
-	tangentQuadraticBezier: function ( t, p0, p1, p2 ) {
+	}
 
 
-		return 2 * ( 1 - t ) * ( p1 - p0 ) + 2 * t * ( p2 - p1 );
+	return ret;
 
 
-	},
+};
 
 
-	// Puay Bing, thanks for helping with this derivative!
+/**************************************************************
+ *	Create Geometries Helpers
+ **************************************************************/
 
 
-	tangentCubicBezier: function (t, p0, p1, p2, p3 ) {
+/// Generate geometry from path points (for Line or ParticleSystem objects)
 
 
-		return -3 * p0 * (1 - t) * (1 - t)  +
-			3 * p1 * (1 - t) * (1-t) - 6 *t *p1 * (1-t) +
-			6 * t *  p2 * (1-t) - 3 * t * t * p2 +
-			3 * t * t * p3;
-	},
+THREE.CurvePath.prototype.createPointsGeometry = function( divisions ) {
 
 
+	var pts = this.getPoints( divisions, true );
+	return this.createGeometry( pts );
 
 
-	tangentSpline: function ( t, p0, p1, p2, p3 ) {
+};
 
 
-		// To check if my formulas are correct
+// Generate geometry from equidistance sampling along the path
 
 
-		var h00 = 6 * t * t - 6 * t; 	// derived from 2t^3 − 3t^2 + 1
-		var h10 = 3 * t * t - 4 * t + 1; // t^3 − 2t^2 + t
-		var h01 = -6 * t * t + 6 * t; 	// − 2t3 + 3t2
-		var h11 = 3 * t * t - 2 * t;	// t3 − t2
+THREE.CurvePath.prototype.createSpacedPointsGeometry = function( divisions ) {
 
 
-		return h00 + h10 + h01 + h11;
+	var pts = this.getSpacedPoints( divisions, true );
+	return this.createGeometry( pts );
 
 
-	},
+};
 
 
-	// Catmull-Rom
+THREE.CurvePath.prototype.createGeometry = function( points ) {
 
 
-	interpolate: function( p0, p1, p2, p3, t ) {
+	var geometry = new THREE.Geometry();
 
 
-		var v0 = ( p2 - p0 ) * 0.5;
-		var v1 = ( p3 - p1 ) * 0.5;
-		var t2 = t * t;
-		var t3 = t * t2;
-		return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
+	for ( var i = 0; i < points.length; i ++ ) {
+
+		geometry.vertices.push( new THREE.Vector3( points[ i ].x, points[ i ].y, points[ i ].z || 0) );
 
 
 	}
 	}
 
 
-};
+	return geometry;
 
 
+};
 
 
-// TODO: Transformation for Curves?
 
 
 /**************************************************************
 /**************************************************************
- *	3D Curves
+ *	Bend / Wrap Helper Methods
  **************************************************************/
  **************************************************************/
 
 
-// A Factory method for creating new curve subclasses
-
-THREE.Curve.create = function ( constructor, getPointFunc ) {
+// Wrap path / Bend modifiers?
 
 
-	constructor.prototype = Object.create( THREE.Curve.prototype );
-	constructor.prototype.getPoint = getPointFunc;
+THREE.CurvePath.prototype.addWrapPath = function ( bendpath ) {
 
 
-	return constructor;
+	this.bends.push( bendpath );
 
 
 };
 };
 
 
+THREE.CurvePath.prototype.getTransformedPoints = function( segments, bends ) {
 
 
-/**************************************************************
- *	Line3D
- **************************************************************/
-
-THREE.LineCurve3 = THREE.Curve.create(
-
-	function ( v1, v2 ) {
+	var oldPts = this.getPoints( segments ); // getPoints getSpacedPoints
+	var i, il;
 
 
-		this.v1 = v1;
-		this.v2 = v2;
+	if ( !bends ) {
 
 
-	},
+		bends = this.bends;
 
 
-	function ( t ) {
+	}
 
 
-		var r = new THREE.Vector3();
+	for ( i = 0, il = bends.length; i < il; i ++ ) {
 
 
+		oldPts = this.getWrapPoints( oldPts, bends[ i ] );
 
 
-		r.subVectors( this.v2, this.v1 ); // diff
-		r.multiplyScalar( t );
-		r.add( this.v1 );
+	}
 
 
-		return r;
+	return oldPts;
 
 
-	}
+};
 
 
-);
+THREE.CurvePath.prototype.getTransformedSpacedPoints = function( segments, bends ) {
 
 
+	var oldPts = this.getSpacedPoints( segments );
 
 
-/**************************************************************
- *	Quadratic Bezier 3D curve
- **************************************************************/
+	var i, il;
 
 
-THREE.QuadraticBezierCurve3 = THREE.Curve.create(
+	if ( !bends ) {
 
 
-	function ( v0, v1, v2 ) {
+		bends = this.bends;
 
 
-		this.v0 = v0;
-		this.v1 = v1;
-		this.v2 = v2;
+	}
 
 
-	},
+	for ( i = 0, il = bends.length; i < il; i ++ ) {
 
 
-	function ( t ) {
+		oldPts = this.getWrapPoints( oldPts, bends[ i ] );
 
 
-		var tx, ty, tz;
+	}
 
 
-		tx = THREE.Shape.Utils.b2( t, this.v0.x, this.v1.x, this.v2.x );
-		ty = THREE.Shape.Utils.b2( t, this.v0.y, this.v1.y, this.v2.y );
-		tz = THREE.Shape.Utils.b2( t, this.v0.z, this.v1.z, this.v2.z );
+	return oldPts;
 
 
-		return new THREE.Vector3( tx, ty, tz );
+};
 
 
-	}
+// This returns getPoints() bend/wrapped around the contour of a path.
+// Read http://www.planetclegg.com/projects/WarpingTextToSplines.html
 
 
-);
+THREE.CurvePath.prototype.getWrapPoints = function ( oldPts, path ) {
 
 
+	var bounds = this.getBoundingBox();
 
 
+	var i, il, p, oldX, oldY, xNorm;
 
 
-/**************************************************************
- *	Cubic Bezier 3D curve
- **************************************************************/
+	for ( i = 0, il = oldPts.length; i < il; i ++ ) {
 
 
-THREE.CubicBezierCurve3 = THREE.Curve.create(
+		p = oldPts[ i ];
 
 
-	function ( v0, v1, v2, v3 ) {
+		oldX = p.x;
+		oldY = p.y;
 
 
-		this.v0 = v0;
-		this.v1 = v1;
-		this.v2 = v2;
-		this.v3 = v3;
+		xNorm = oldX / bounds.maxX;
 
 
-	},
+		// If using actual distance, for length > path, requires line extrusions
+		//xNorm = path.getUtoTmapping(xNorm, oldX); // 3 styles. 1) wrap stretched. 2) wrap stretch by arc length 3) warp by actual distance
 
 
-	function ( t ) {
+		xNorm = path.getUtoTmapping( xNorm, oldX );
 
 
-		var tx, ty, tz;
+		// check for out of bounds?
 
 
-		tx = THREE.Shape.Utils.b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
-		ty = THREE.Shape.Utils.b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
-		tz = THREE.Shape.Utils.b3( t, this.v0.z, this.v1.z, this.v2.z, this.v3.z );
+		var pathPt = path.getPoint( xNorm );
+		var normal = path.getNormalVector( xNorm ).multiplyScalar( oldY );
 
 
-		return new THREE.Vector3( tx, ty, tz );
+		p.x = pathPt.x + normal.x;
+		p.y = pathPt.y + normal.y;
 
 
 	}
 	}
 
 
-);
+	return oldPts;
 
 
+};
 
 
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.Gyroscope = function () {
+
+	THREE.Object3D.call( this );
+
+};
+
+THREE.Gyroscope.prototype = Object.create( THREE.Object3D.prototype );
+
+THREE.Gyroscope.prototype.updateMatrixWorld = function ( force ) {
+
+	this.matrixAutoUpdate && this.updateMatrix();
+
+	// update matrixWorld
+
+	if ( this.matrixWorldNeedsUpdate || force ) {
+
+		if ( this.parent ) {
+
+			this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
+
+			this.matrixWorld.decompose( this.translationWorld, this.rotationWorld, this.scaleWorld );
+			this.matrix.decompose( this.translationObject, this.rotationObject, this.scaleObject );
+
+			this.matrixWorld.makeFromPositionQuaternionScale( this.translationWorld, this.rotationObject, this.scaleWorld );
+
+
+		} else {
+
+			this.matrixWorld.copy( this.matrix );
+
+		}
+
+
+		this.matrixWorldNeedsUpdate = false;
+
+		force = true;
+
+	}
+
+	// update children
+
+	for ( var i = 0, l = this.children.length; i < l; i ++ ) {
+
+		this.children[ i ].updateMatrixWorld( force );
+
+	}
+
+};
+
+THREE.Gyroscope.prototype.translationWorld = new THREE.Vector3();
+THREE.Gyroscope.prototype.translationObject = new THREE.Vector3();
+THREE.Gyroscope.prototype.rotationWorld = new THREE.Quaternion();
+THREE.Gyroscope.prototype.rotationObject = new THREE.Quaternion();
+THREE.Gyroscope.prototype.scaleWorld = new THREE.Vector3();
+THREE.Gyroscope.prototype.scaleObject = new THREE.Vector3();
+
+/**
+ * @author zz85 / http://www.lab4games.net/zz85/blog
+ * Creates free form 2d path using series of points, lines or curves.
+ *
+ **/
 
 
-/**************************************************************
- *	Spline 3D curve
- **************************************************************/
+THREE.Path = function ( points ) {
 
 
+	THREE.CurvePath.call(this);
 
 
-THREE.SplineCurve3 = THREE.Curve.create(
+	this.actions = [];
 
 
-	function ( points /* array of Vector3 */) {
+	if ( points ) {
 
 
-		this.points = (points == undefined) ? [] : points;
+		this.fromPoints( points );
 
 
-	},
+	}
 
 
-	function ( t ) {
-
-		var v = new THREE.Vector3();
-		var c = [];
-		var points = this.points, point, intPoint, weight;
-		point = ( points.length - 1 ) * t;
-
-		intPoint = Math.floor( point );
-		weight = point - intPoint;
-
-		c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
-		c[ 1 ] = intPoint;
-		c[ 2 ] = intPoint  > points.length - 2 ? points.length - 1 : intPoint + 1;
-		c[ 3 ] = intPoint  > points.length - 3 ? points.length - 1 : intPoint + 2;
-
-		var pt0 = points[ c[0] ],
-			pt1 = points[ c[1] ],
-			pt2 = points[ c[2] ],
-			pt3 = points[ c[3] ];
-
-		v.x = THREE.Curve.Utils.interpolate(pt0.x, pt1.x, pt2.x, pt3.x, weight);
-		v.y = THREE.Curve.Utils.interpolate(pt0.y, pt1.y, pt2.y, pt3.y, weight);
-		v.z = THREE.Curve.Utils.interpolate(pt0.z, pt1.z, pt2.z, pt3.z, weight);
-
-		return v;
-
-	}
-
-);
-
-
-// THREE.SplineCurve3.prototype.getTangent = function(t) {
-// 		var v = new THREE.Vector3();
-// 		var c = [];
-// 		var points = this.points, point, intPoint, weight;
-// 		point = ( points.length - 1 ) * t;
-
-// 		intPoint = Math.floor( point );
-// 		weight = point - intPoint;
-
-// 		c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
-// 		c[ 1 ] = intPoint;
-// 		c[ 2 ] = intPoint  > points.length - 2 ? points.length - 1 : intPoint + 1;
-// 		c[ 3 ] = intPoint  > points.length - 3 ? points.length - 1 : intPoint + 2;
-
-// 		var pt0 = points[ c[0] ],
-// 			pt1 = points[ c[1] ],
-// 			pt2 = points[ c[2] ],
-// 			pt3 = points[ c[3] ];
-
-// 	// t = weight;
-// 	v.x = THREE.Curve.Utils.tangentSpline( t, pt0.x, pt1.x, pt2.x, pt3.x );
-// 	v.y = THREE.Curve.Utils.tangentSpline( t, pt0.y, pt1.y, pt2.y, pt3.y );
-// 	v.z = THREE.Curve.Utils.tangentSpline( t, pt0.z, pt1.z, pt2.z, pt3.z );
-
-// 	return v;
-
-// }
+};
 
 
-/**************************************************************
- *	Closed Spline 3D curve
- **************************************************************/
+THREE.Path.prototype = Object.create( THREE.CurvePath.prototype );
 
 
+THREE.PathActions = {
 
 
-THREE.ClosedSplineCurve3 = THREE.Curve.create(
+	MOVE_TO: 'moveTo',
+	LINE_TO: 'lineTo',
+	QUADRATIC_CURVE_TO: 'quadraticCurveTo', // Bezier quadratic curve
+	BEZIER_CURVE_TO: 'bezierCurveTo', 		// Bezier cubic curve
+	CSPLINE_THRU: 'splineThru',				// Catmull-rom spline
+	ARC: 'arc',								// Circle
+	ELLIPSE: 'ellipse'
+};
 
 
-	function ( points /* array of Vector3 */) {
+// TODO Clean up PATH API
 
 
-		this.points = (points == undefined) ? [] : points;
+// Create path using straight lines to connect all points
+// - vectors: array of Vector2
 
 
-	},
+THREE.Path.prototype.fromPoints = function ( vectors ) {
 
 
-    function ( t ) {
+	this.moveTo( vectors[ 0 ].x, vectors[ 0 ].y );
 
 
-        var v = new THREE.Vector3();
-        var c = [];
-        var points = this.points, point, intPoint, weight;
-        point = ( points.length - 0 ) * t;
-            // This needs to be from 0-length +1
+	for ( var v = 1, vlen = vectors.length; v < vlen; v ++ ) {
 
 
-        intPoint = Math.floor( point );
-        weight = point - intPoint;
+		this.lineTo( vectors[ v ].x, vectors[ v ].y );
 
 
-        intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / points.length ) + 1 ) * points.length;
-        c[ 0 ] = ( intPoint - 1 ) % points.length;
-        c[ 1 ] = ( intPoint ) % points.length;
-        c[ 2 ] = ( intPoint + 1 ) % points.length;
-        c[ 3 ] = ( intPoint + 2 ) % points.length;
+	};
 
 
-        v.x = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight );
-        v.y = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight );
-        v.z = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].z, points[ c[ 1 ] ].z, points[ c[ 2 ] ].z, points[ c[ 3 ] ].z, weight );
+};
 
 
-        return v;
+// startPath() endPath()?
 
 
-    }
+THREE.Path.prototype.moveTo = function ( x, y ) {
 
 
-);
-/**
- * @author zz85 / http://www.lab4games.net/zz85/blog
- *
- **/
+	var args = Array.prototype.slice.call( arguments );
+	this.actions.push( { action: THREE.PathActions.MOVE_TO, args: args } );
 
 
-/**************************************************************
- *	Curved Path - a curve path is simply a array of connected
- *  curves, but retains the api of a curve
- **************************************************************/
+};
 
 
-THREE.CurvePath = function () {
+THREE.Path.prototype.lineTo = function ( x, y ) {
 
 
-	this.curves = [];
-	this.bends = [];
-	
-	this.autoClose = false; // Automatically closes the path
-};
+	var args = Array.prototype.slice.call( arguments );
 
 
-THREE.CurvePath.prototype = Object.create( THREE.Curve.prototype );
+	var lastargs = this.actions[ this.actions.length - 1 ].args;
 
 
-THREE.CurvePath.prototype.add = function ( curve ) {
+	var x0 = lastargs[ lastargs.length - 2 ];
+	var y0 = lastargs[ lastargs.length - 1 ];
 
 
+	var curve = new THREE.LineCurve( new THREE.Vector2( x0, y0 ), new THREE.Vector2( x, y ) );
 	this.curves.push( curve );
 	this.curves.push( curve );
 
 
-};
+	this.actions.push( { action: THREE.PathActions.LINE_TO, args: args } );
 
 
-THREE.CurvePath.prototype.checkConnection = function() {
-	// TODO
-	// If the ending of curve is not connected to the starting
-	// or the next curve, then, this is not a real path
 };
 };
 
 
-THREE.CurvePath.prototype.closePath = function() {
-	// TODO Test
-	// and verify for vector3 (needs to implement equals)
-	// Add a line curve if start and end of lines are not connected
-	var startPoint = this.curves[0].getPoint(0);
-	var endPoint = this.curves[this.curves.length-1].getPoint(1);
-	
-	if (!startPoint.equals(endPoint)) {
-		this.curves.push( new THREE.LineCurve(endPoint, startPoint) );
-	}
-	
-};
-
-// To get accurate point with reference to
-// entire path distance at time t,
-// following has to be done:
-
-// 1. Length of each sub path have to be known
-// 2. Locate and identify type of curve
-// 3. Get t for the curve
-// 4. Return curve.getPointAt(t')
-
-THREE.CurvePath.prototype.getPoint = function( t ) {
+THREE.Path.prototype.quadraticCurveTo = function( aCPx, aCPy, aX, aY ) {
 
 
-	var d = t * this.getLength();
-	var curveLengths = this.getCurveLengths();
-	var i = 0, diff, curve;
+	var args = Array.prototype.slice.call( arguments );
 
 
-	// To think about boundaries points.
+	var lastargs = this.actions[ this.actions.length - 1 ].args;
 
 
-	while ( i < curveLengths.length ) {
+	var x0 = lastargs[ lastargs.length - 2 ];
+	var y0 = lastargs[ lastargs.length - 1 ];
 
 
-		if ( curveLengths[ i ] >= d ) {
+	var curve = new THREE.QuadraticBezierCurve( new THREE.Vector2( x0, y0 ),
+												new THREE.Vector2( aCPx, aCPy ),
+												new THREE.Vector2( aX, aY ) );
+	this.curves.push( curve );
 
 
-			diff = curveLengths[ i ] - d;
-			curve = this.curves[ i ];
+	this.actions.push( { action: THREE.PathActions.QUADRATIC_CURVE_TO, args: args } );
 
 
-			var u = 1 - diff / curve.getLength();
+};
 
 
-			return curve.getPointAt( u );
+THREE.Path.prototype.bezierCurveTo = function( aCP1x, aCP1y,
+                                               aCP2x, aCP2y,
+                                               aX, aY ) {
 
 
-			break;
-		}
+	var args = Array.prototype.slice.call( arguments );
 
 
-		i ++;
+	var lastargs = this.actions[ this.actions.length - 1 ].args;
 
 
-	}
+	var x0 = lastargs[ lastargs.length - 2 ];
+	var y0 = lastargs[ lastargs.length - 1 ];
 
 
-	return null;
+	var curve = new THREE.CubicBezierCurve( new THREE.Vector2( x0, y0 ),
+											new THREE.Vector2( aCP1x, aCP1y ),
+											new THREE.Vector2( aCP2x, aCP2y ),
+											new THREE.Vector2( aX, aY ) );
+	this.curves.push( curve );
 
 
-	// loop where sum != 0, sum > d , sum+1 <d
+	this.actions.push( { action: THREE.PathActions.BEZIER_CURVE_TO, args: args } );
 
 
 };
 };
 
 
-/*
-THREE.CurvePath.prototype.getTangent = function( t ) {
-};*/
+THREE.Path.prototype.splineThru = function( pts /*Array of Vector*/ ) {
 
 
+	var args = Array.prototype.slice.call( arguments );
+	var lastargs = this.actions[ this.actions.length - 1 ].args;
 
 
-// We cannot use the default THREE.Curve getPoint() with getLength() because in
-// THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
-// getPoint() depends on getLength
+	var x0 = lastargs[ lastargs.length - 2 ];
+	var y0 = lastargs[ lastargs.length - 1 ];
+//---
+	var npts = [ new THREE.Vector2( x0, y0 ) ];
+	Array.prototype.push.apply( npts, pts );
 
 
-THREE.CurvePath.prototype.getLength = function() {
+	var curve = new THREE.SplineCurve( npts );
+	this.curves.push( curve );
 
 
-	var lens = this.getCurveLengths();
-	return lens[ lens.length - 1 ];
+	this.actions.push( { action: THREE.PathActions.CSPLINE_THRU, args: args } );
 
 
 };
 };
 
 
-// Compute lengths and cache them
-// We cannot overwrite getLengths() because UtoT mapping uses it.
-
-THREE.CurvePath.prototype.getCurveLengths = function() {
-
-	// We use cache values if curves and cache array are same length
-
-	if ( this.cacheLengths && this.cacheLengths.length == this.curves.length ) {
-
-		return this.cacheLengths;
-
-	};
-
-	// Get length of subsurve
-	// Push sums into cached array
-
-	var lengths = [], sums = 0;
-	var i, il = this.curves.length;
+// FUTURE: Change the API or follow canvas API?
 
 
-	for ( i = 0; i < il; i ++ ) {
+THREE.Path.prototype.arc = function ( aX, aY, aRadius,
+									  aStartAngle, aEndAngle, aClockwise ) {
 
 
-		sums += this.curves[ i ].getLength();
-		lengths.push( sums );
+	var lastargs = this.actions[ this.actions.length - 1].args;
+	var x0 = lastargs[ lastargs.length - 2 ];
+	var y0 = lastargs[ lastargs.length - 1 ];
 
 
-	}
+	this.absarc(aX + x0, aY + y0, aRadius,
+		aStartAngle, aEndAngle, aClockwise );
+	
+ };
 
 
-	this.cacheLengths = lengths;
+ THREE.Path.prototype.absarc = function ( aX, aY, aRadius,
+									  aStartAngle, aEndAngle, aClockwise ) {
+	this.absellipse(aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise);
+ };
+ 
+THREE.Path.prototype.ellipse = function ( aX, aY, xRadius, yRadius,
+									  aStartAngle, aEndAngle, aClockwise ) {
 
 
-	return lengths;
+	var lastargs = this.actions[ this.actions.length - 1].args;
+	var x0 = lastargs[ lastargs.length - 2 ];
+	var y0 = lastargs[ lastargs.length - 1 ];
 
 
-};
+	this.absellipse(aX + x0, aY + y0, xRadius, yRadius,
+		aStartAngle, aEndAngle, aClockwise );
 
 
+ };
+ 
 
 
+THREE.Path.prototype.absellipse = function ( aX, aY, xRadius, yRadius,
+									  aStartAngle, aEndAngle, aClockwise ) {
 
 
-// Returns min and max coordinates, as well as centroid
+	var args = Array.prototype.slice.call( arguments );
+	var curve = new THREE.EllipseCurve( aX, aY, xRadius, yRadius,
+									aStartAngle, aEndAngle, aClockwise );
+	this.curves.push( curve );
 
 
-THREE.CurvePath.prototype.getBoundingBox = function () {
+	var lastPoint = curve.getPoint(aClockwise ? 1 : 0);
+	args.push(lastPoint.x);
+	args.push(lastPoint.y);
 
 
-	var points = this.getPoints();
+	this.actions.push( { action: THREE.PathActions.ELLIPSE, args: args } );
 
 
-	var maxX, maxY, maxZ;
-	var minX, minY, minZ;
+ };
 
 
-	maxX = maxY = Number.NEGATIVE_INFINITY;
-	minX = minY = Number.POSITIVE_INFINITY;
+THREE.Path.prototype.getSpacedPoints = function ( divisions, closedPath ) {
 
 
-	var p, i, il, sum;
+	if ( ! divisions ) divisions = 40;
 
 
-	var v3 = points[0] instanceof THREE.Vector3;
+	var points = [];
 
 
-	sum = v3 ? new THREE.Vector3() : new THREE.Vector2();
+	for ( var i = 0; i < divisions; i ++ ) {
 
 
-	for ( i = 0, il = points.length; i < il; i ++ ) {
+		points.push( this.getPoint( i / divisions ) );
 
 
-		p = points[ i ];
+		//if( !this.getPoint( i / divisions ) ) throw "DIE";
 
 
-		if ( p.x > maxX ) maxX = p.x;
-		else if ( p.x < minX ) minX = p.x;
+	}
 
 
-		if ( p.y > maxY ) maxY = p.y;
-		else if ( p.y < minY ) minY = p.y;
+	// if ( closedPath ) {
+	//
+	// 	points.push( points[ 0 ] );
+	//
+	// }
 
 
-		if ( v3 ) {
+	return points;
 
 
-			if ( p.z > maxZ ) maxZ = p.z;
-			else if ( p.z < minZ ) minZ = p.z;
+};
 
 
-		}
+/* Return an array of vectors based on contour of the path */
 
 
-		sum.add( p );
+THREE.Path.prototype.getPoints = function( divisions, closedPath ) {
 
 
+	if (this.useSpacedPoints) {
+		console.log('tata');
+		return this.getSpacedPoints( divisions, closedPath );
 	}
 	}
 
 
-	var ret = {
-
-		minX: minX,
-		minY: minY,
-		maxX: maxX,
-		maxY: maxY,
-		centroid: sum.divideScalar( il )
+	divisions = divisions || 12;
 
 
-	};
+	var points = [];
 
 
-	if ( v3 ) {
+	var i, il, item, action, args;
+	var cpx, cpy, cpx2, cpy2, cpx1, cpy1, cpx0, cpy0,
+		laste, j,
+		t, tx, ty;
 
 
-		ret.maxZ = maxZ;
-		ret.minZ = minZ;
+	for ( i = 0, il = this.actions.length; i < il; i ++ ) {
 
 
-	}
+		item = this.actions[ i ];
 
 
-	return ret;
+		action = item.action;
+		args = item.args;
 
 
-};
+		switch( action ) {
 
 
-/**************************************************************
- *	Create Geometries Helpers
- **************************************************************/
+		case THREE.PathActions.MOVE_TO:
 
 
-/// Generate geometry from path points (for Line or ParticleSystem objects)
+			points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
 
 
-THREE.CurvePath.prototype.createPointsGeometry = function( divisions ) {
+			break;
 
 
-	var pts = this.getPoints( divisions, true );
-	return this.createGeometry( pts );
+		case THREE.PathActions.LINE_TO:
 
 
-};
+			points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
 
 
-// Generate geometry from equidistance sampling along the path
+			break;
 
 
-THREE.CurvePath.prototype.createSpacedPointsGeometry = function( divisions ) {
+		case THREE.PathActions.QUADRATIC_CURVE_TO:
 
 
-	var pts = this.getSpacedPoints( divisions, true );
-	return this.createGeometry( pts );
+			cpx  = args[ 2 ];
+			cpy  = args[ 3 ];
 
 
-};
+			cpx1 = args[ 0 ];
+			cpy1 = args[ 1 ];
 
 
-THREE.CurvePath.prototype.createGeometry = function( points ) {
+			if ( points.length > 0 ) {
 
 
-	var geometry = new THREE.Geometry();
+				laste = points[ points.length - 1 ];
 
 
-	for ( var i = 0; i < points.length; i ++ ) {
+				cpx0 = laste.x;
+				cpy0 = laste.y;
 
 
-		geometry.vertices.push( new THREE.Vector3( points[ i ].x, points[ i ].y, points[ i ].z || 0) );
+			} else {
 
 
-	}
+				laste = this.actions[ i - 1 ].args;
 
 
-	return geometry;
+				cpx0 = laste[ laste.length - 2 ];
+				cpy0 = laste[ laste.length - 1 ];
 
 
-};
+			}
 
 
+			for ( j = 1; j <= divisions; j ++ ) {
 
 
-/**************************************************************
- *	Bend / Wrap Helper Methods
- **************************************************************/
+				t = j / divisions;
 
 
-// Wrap path / Bend modifiers?
+				tx = THREE.Shape.Utils.b2( t, cpx0, cpx1, cpx );
+				ty = THREE.Shape.Utils.b2( t, cpy0, cpy1, cpy );
 
 
-THREE.CurvePath.prototype.addWrapPath = function ( bendpath ) {
+				points.push( new THREE.Vector2( tx, ty ) );
 
 
-	this.bends.push( bendpath );
+		  	}
 
 
-};
+			break;
 
 
-THREE.CurvePath.prototype.getTransformedPoints = function( segments, bends ) {
+		case THREE.PathActions.BEZIER_CURVE_TO:
 
 
-	var oldPts = this.getPoints( segments ); // getPoints getSpacedPoints
-	var i, il;
+			cpx  = args[ 4 ];
+			cpy  = args[ 5 ];
 
 
-	if ( !bends ) {
+			cpx1 = args[ 0 ];
+			cpy1 = args[ 1 ];
 
 
-		bends = this.bends;
+			cpx2 = args[ 2 ];
+			cpy2 = args[ 3 ];
 
 
-	}
+			if ( points.length > 0 ) {
 
 
-	for ( i = 0, il = bends.length; i < il; i ++ ) {
+				laste = points[ points.length - 1 ];
 
 
-		oldPts = this.getWrapPoints( oldPts, bends[ i ] );
+				cpx0 = laste.x;
+				cpy0 = laste.y;
 
 
-	}
+			} else {
 
 
-	return oldPts;
+				laste = this.actions[ i - 1 ].args;
 
 
-};
+				cpx0 = laste[ laste.length - 2 ];
+				cpy0 = laste[ laste.length - 1 ];
 
 
-THREE.CurvePath.prototype.getTransformedSpacedPoints = function( segments, bends ) {
+			}
 
 
-	var oldPts = this.getSpacedPoints( segments );
 
 
-	var i, il;
+			for ( j = 1; j <= divisions; j ++ ) {
 
 
-	if ( !bends ) {
+				t = j / divisions;
 
 
-		bends = this.bends;
+				tx = THREE.Shape.Utils.b3( t, cpx0, cpx1, cpx2, cpx );
+				ty = THREE.Shape.Utils.b3( t, cpy0, cpy1, cpy2, cpy );
 
 
-	}
+				points.push( new THREE.Vector2( tx, ty ) );
 
 
-	for ( i = 0, il = bends.length; i < il; i ++ ) {
+			}
 
 
-		oldPts = this.getWrapPoints( oldPts, bends[ i ] );
+			break;
 
 
-	}
+		case THREE.PathActions.CSPLINE_THRU:
 
 
-	return oldPts;
+			laste = this.actions[ i - 1 ].args;
 
 
-};
+			var last = new THREE.Vector2( laste[ laste.length - 2 ], laste[ laste.length - 1 ] );
+			var spts = [ last ];
 
 
-// This returns getPoints() bend/wrapped around the contour of a path.
-// Read http://www.planetclegg.com/projects/WarpingTextToSplines.html
+			var n = divisions * args[ 0 ].length;
 
 
-THREE.CurvePath.prototype.getWrapPoints = function ( oldPts, path ) {
+			spts = spts.concat( args[ 0 ] );
 
 
-	var bounds = this.getBoundingBox();
+			var spline = new THREE.SplineCurve( spts );
 
 
-	var i, il, p, oldX, oldY, xNorm;
+			for ( j = 1; j <= n; j ++ ) {
 
 
-	for ( i = 0, il = oldPts.length; i < il; i ++ ) {
+				points.push( spline.getPointAt( j / n ) ) ;
 
 
-		p = oldPts[ i ];
+			}
 
 
-		oldX = p.x;
-		oldY = p.y;
+			break;
 
 
-		xNorm = oldX / bounds.maxX;
+		case THREE.PathActions.ARC:
 
 
-		// If using actual distance, for length > path, requires line extrusions
-		//xNorm = path.getUtoTmapping(xNorm, oldX); // 3 styles. 1) wrap stretched. 2) wrap stretch by arc length 3) warp by actual distance
+			var aX = args[ 0 ], aY = args[ 1 ],
+				aRadius = args[ 2 ],
+				aStartAngle = args[ 3 ], aEndAngle = args[ 4 ],
+				aClockwise = !!args[ 5 ];
 
 
-		xNorm = path.getUtoTmapping( xNorm, oldX );
+			var deltaAngle = aEndAngle - aStartAngle;
+			var angle;
+			var tdivisions = divisions * 2;
 
 
-		// check for out of bounds?
+			for ( j = 1; j <= tdivisions; j ++ ) {
 
 
-		var pathPt = path.getPoint( xNorm );
-		var normal = path.getNormalVector( xNorm ).multiplyScalar( oldY );
+				t = j / tdivisions;
 
 
-		p.x = pathPt.x + normal.x;
-		p.y = pathPt.y + normal.y;
+				if ( ! aClockwise ) {
 
 
-	}
+					t = 1 - t;
 
 
-	return oldPts;
+				}
 
 
-};
+				angle = aStartAngle + t * deltaAngle;
 
 
-/**
- * @author alteredq / http://alteredqualia.com/
- */
-
-THREE.Gyroscope = function () {
-
-	THREE.Object3D.call( this );
-
-};
-
-THREE.Gyroscope.prototype = Object.create( THREE.Object3D.prototype );
-
-THREE.Gyroscope.prototype.updateMatrixWorld = function ( force ) {
-
-	this.matrixAutoUpdate && this.updateMatrix();
-
-	// update matrixWorld
-
-	if ( this.matrixWorldNeedsUpdate || force ) {
-
-		if ( this.parent ) {
-
-			this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
-
-			this.matrixWorld.decompose( this.translationWorld, this.rotationWorld, this.scaleWorld );
-			this.matrix.decompose( this.translationObject, this.rotationObject, this.scaleObject );
-
-			this.matrixWorld.makeFromPositionQuaternionScale( this.translationWorld, this.rotationObject, this.scaleWorld );
-
-
-		} else {
-
-			this.matrixWorld.copy( this.matrix );
-
-		}
-
-
-		this.matrixWorldNeedsUpdate = false;
-
-		force = true;
-
-	}
-
-	// update children
-
-	for ( var i = 0, l = this.children.length; i < l; i ++ ) {
-
-		this.children[ i ].updateMatrixWorld( force );
-
-	}
-
-};
-
-THREE.Gyroscope.prototype.translationWorld = new THREE.Vector3();
-THREE.Gyroscope.prototype.translationObject = new THREE.Vector3();
-THREE.Gyroscope.prototype.rotationWorld = new THREE.Quaternion();
-THREE.Gyroscope.prototype.rotationObject = new THREE.Quaternion();
-THREE.Gyroscope.prototype.scaleWorld = new THREE.Vector3();
-THREE.Gyroscope.prototype.scaleObject = new THREE.Vector3();
-
-/**
- * @author zz85 / http://www.lab4games.net/zz85/blog
- * Creates free form 2d path using series of points, lines or curves.
- *
- **/
+				tx = aX + aRadius * Math.cos( angle );
+				ty = aY + aRadius * Math.sin( angle );
 
 
-THREE.Path = function ( points ) {
+				//console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
 
 
-	THREE.CurvePath.call(this);
+				points.push( new THREE.Vector2( tx, ty ) );
 
 
-	this.actions = [];
+			}
 
 
-	if ( points ) {
+			//console.log(points);
 
 
-		this.fromPoints( points );
+		  break;
+		  
+		case THREE.PathActions.ELLIPSE:
 
 
-	}
+			var aX = args[ 0 ], aY = args[ 1 ],
+				xRadius = args[ 2 ],
+				yRadius = args[ 3 ],
+				aStartAngle = args[ 4 ], aEndAngle = args[ 5 ],
+				aClockwise = !!args[ 6 ];
 
 
-};
 
 
-THREE.Path.prototype = Object.create( THREE.CurvePath.prototype );
+			var deltaAngle = aEndAngle - aStartAngle;
+			var angle;
+			var tdivisions = divisions * 2;
 
 
-THREE.PathActions = {
+			for ( j = 1; j <= tdivisions; j ++ ) {
 
 
-	MOVE_TO: 'moveTo',
-	LINE_TO: 'lineTo',
-	QUADRATIC_CURVE_TO: 'quadraticCurveTo', // Bezier quadratic curve
-	BEZIER_CURVE_TO: 'bezierCurveTo', 		// Bezier cubic curve
-	CSPLINE_THRU: 'splineThru',				// Catmull-rom spline
-	ARC: 'arc',								// Circle
-	ELLIPSE: 'ellipse'
-};
+				t = j / tdivisions;
 
 
-// TODO Clean up PATH API
+				if ( ! aClockwise ) {
 
 
-// Create path using straight lines to connect all points
-// - vectors: array of Vector2
+					t = 1 - t;
 
 
-THREE.Path.prototype.fromPoints = function ( vectors ) {
+				}
 
 
-	this.moveTo( vectors[ 0 ].x, vectors[ 0 ].y );
+				angle = aStartAngle + t * deltaAngle;
 
 
-	for ( var v = 1, vlen = vectors.length; v < vlen; v ++ ) {
+				tx = aX + xRadius * Math.cos( angle );
+				ty = aY + yRadius * Math.sin( angle );
 
 
-		this.lineTo( vectors[ v ].x, vectors[ v ].y );
+				//console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
 
 
-	};
+				points.push( new THREE.Vector2( tx, ty ) );
 
 
-};
+			}
 
 
-// startPath() endPath()?
+			//console.log(points);
 
 
-THREE.Path.prototype.moveTo = function ( x, y ) {
+		  break;
 
 
-	var args = Array.prototype.slice.call( arguments );
-	this.actions.push( { action: THREE.PathActions.MOVE_TO, args: args } );
+		} // end switch
 
 
-};
+	}
 
 
-THREE.Path.prototype.lineTo = function ( x, y ) {
 
 
-	var args = Array.prototype.slice.call( arguments );
 
 
-	var lastargs = this.actions[ this.actions.length - 1 ].args;
+	// Normalize to remove the closing point by default.
+	var lastPoint = points[ points.length - 1];
+	var EPSILON = 0.0000000001;
+	if ( Math.abs(lastPoint.x - points[ 0 ].x) < EPSILON &&
+             Math.abs(lastPoint.y - points[ 0 ].y) < EPSILON)
+		points.splice( points.length - 1, 1);
+	if ( closedPath ) {
 
 
-	var x0 = lastargs[ lastargs.length - 2 ];
-	var y0 = lastargs[ lastargs.length - 1 ];
+		points.push( points[ 0 ] );
 
 
-	var curve = new THREE.LineCurve( new THREE.Vector2( x0, y0 ), new THREE.Vector2( x, y ) );
-	this.curves.push( curve );
+	}
 
 
-	this.actions.push( { action: THREE.PathActions.LINE_TO, args: args } );
+	return points;
 
 
 };
 };
 
 
-THREE.Path.prototype.quadraticCurveTo = function( aCPx, aCPy, aX, aY ) {
+// Breaks path into shapes
 
 
-	var args = Array.prototype.slice.call( arguments );
+THREE.Path.prototype.toShapes = function() {
 
 
-	var lastargs = this.actions[ this.actions.length - 1 ].args;
+	var i, il, item, action, args;
 
 
-	var x0 = lastargs[ lastargs.length - 2 ];
-	var y0 = lastargs[ lastargs.length - 1 ];
+	var subPaths = [], lastPath = new THREE.Path();
 
 
-	var curve = new THREE.QuadraticBezierCurve( new THREE.Vector2( x0, y0 ),
-												new THREE.Vector2( aCPx, aCPy ),
-												new THREE.Vector2( aX, aY ) );
-	this.curves.push( curve );
+	for ( i = 0, il = this.actions.length; i < il; i ++ ) {
 
 
-	this.actions.push( { action: THREE.PathActions.QUADRATIC_CURVE_TO, args: args } );
+		item = this.actions[ i ];
 
 
-};
+		args = item.args;
+		action = item.action;
 
 
-THREE.Path.prototype.bezierCurveTo = function( aCP1x, aCP1y,
-                                               aCP2x, aCP2y,
-                                               aX, aY ) {
+		if ( action == THREE.PathActions.MOVE_TO ) {
 
 
-	var args = Array.prototype.slice.call( arguments );
+			if ( lastPath.actions.length != 0 ) {
 
 
-	var lastargs = this.actions[ this.actions.length - 1 ].args;
+				subPaths.push( lastPath );
+				lastPath = new THREE.Path();
 
 
-	var x0 = lastargs[ lastargs.length - 2 ];
-	var y0 = lastargs[ lastargs.length - 1 ];
+			}
 
 
-	var curve = new THREE.CubicBezierCurve( new THREE.Vector2( x0, y0 ),
-											new THREE.Vector2( aCP1x, aCP1y ),
-											new THREE.Vector2( aCP2x, aCP2y ),
-											new THREE.Vector2( aX, aY ) );
-	this.curves.push( curve );
+		}
 
 
-	this.actions.push( { action: THREE.PathActions.BEZIER_CURVE_TO, args: args } );
+		lastPath[ action ].apply( lastPath, args );
 
 
-};
+	}
 
 
-THREE.Path.prototype.splineThru = function( pts /*Array of Vector*/ ) {
+	if ( lastPath.actions.length != 0 ) {
 
 
-	var args = Array.prototype.slice.call( arguments );
-	var lastargs = this.actions[ this.actions.length - 1 ].args;
+		subPaths.push( lastPath );
 
 
-	var x0 = lastargs[ lastargs.length - 2 ];
-	var y0 = lastargs[ lastargs.length - 1 ];
-//---
-	var npts = [ new THREE.Vector2( x0, y0 ) ];
-	Array.prototype.push.apply( npts, pts );
+	}
 
 
-	var curve = new THREE.SplineCurve( npts );
-	this.curves.push( curve );
+	// console.log(subPaths);
 
 
-	this.actions.push( { action: THREE.PathActions.CSPLINE_THRU, args: args } );
+	if ( subPaths.length == 0 ) return [];
 
 
-};
+	var tmpPath, tmpShape, shapes = [];
 
 
-// FUTURE: Change the API or follow canvas API?
+	var holesFirst = !THREE.Shape.Utils.isClockWise( subPaths[ 0 ].getPoints() );
+	// console.log("Holes first", holesFirst);
 
 
-THREE.Path.prototype.arc = function ( aX, aY, aRadius,
-									  aStartAngle, aEndAngle, aClockwise ) {
+	if ( subPaths.length == 1) {
+		tmpPath = subPaths[0];
+		tmpShape = new THREE.Shape();
+		tmpShape.actions = tmpPath.actions;
+		tmpShape.curves = tmpPath.curves;
+		shapes.push( tmpShape );
+		return shapes;
+	};
 
 
-	var lastargs = this.actions[ this.actions.length - 1].args;
-	var x0 = lastargs[ lastargs.length - 2 ];
-	var y0 = lastargs[ lastargs.length - 1 ];
+	if ( holesFirst ) {
 
 
-	this.absarc(aX + x0, aY + y0, aRadius,
-		aStartAngle, aEndAngle, aClockwise );
-	
- };
+		tmpShape = new THREE.Shape();
 
 
- THREE.Path.prototype.absarc = function ( aX, aY, aRadius,
-									  aStartAngle, aEndAngle, aClockwise ) {
-	this.absellipse(aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise);
- };
- 
-THREE.Path.prototype.ellipse = function ( aX, aY, xRadius, yRadius,
-									  aStartAngle, aEndAngle, aClockwise ) {
+		for ( i = 0, il = subPaths.length; i < il; i ++ ) {
 
 
-	var lastargs = this.actions[ this.actions.length - 1].args;
-	var x0 = lastargs[ lastargs.length - 2 ];
-	var y0 = lastargs[ lastargs.length - 1 ];
+			tmpPath = subPaths[ i ];
 
 
-	this.absellipse(aX + x0, aY + y0, xRadius, yRadius,
-		aStartAngle, aEndAngle, aClockwise );
+			if ( THREE.Shape.Utils.isClockWise( tmpPath.getPoints() ) ) {
 
 
- };
- 
+				tmpShape.actions = tmpPath.actions;
+				tmpShape.curves = tmpPath.curves;
 
 
-THREE.Path.prototype.absellipse = function ( aX, aY, xRadius, yRadius,
-									  aStartAngle, aEndAngle, aClockwise ) {
+				shapes.push( tmpShape );
+				tmpShape = new THREE.Shape();
 
 
-	var args = Array.prototype.slice.call( arguments );
-	var curve = new THREE.EllipseCurve( aX, aY, xRadius, yRadius,
-									aStartAngle, aEndAngle, aClockwise );
-	this.curves.push( curve );
+				//console.log('cw', i);
 
 
-	var lastPoint = curve.getPoint(aClockwise ? 1 : 0);
-	args.push(lastPoint.x);
-	args.push(lastPoint.y);
+			} else {
 
 
-	this.actions.push( { action: THREE.PathActions.ELLIPSE, args: args } );
+				tmpShape.holes.push( tmpPath );
 
 
- };
+				//console.log('ccw', i);
 
 
-THREE.Path.prototype.getSpacedPoints = function ( divisions, closedPath ) {
+			}
 
 
-	if ( ! divisions ) divisions = 40;
+		}
 
 
-	var points = [];
+	} else {
 
 
-	for ( var i = 0; i < divisions; i ++ ) {
+		// Shapes first
 
 
-		points.push( this.getPoint( i / divisions ) );
+		for ( i = 0, il = subPaths.length; i < il; i ++ ) {
 
 
-		//if( !this.getPoint( i / divisions ) ) throw "DIE";
+			tmpPath = subPaths[ i ];
 
 
-	}
+			if ( THREE.Shape.Utils.isClockWise( tmpPath.getPoints() ) ) {
 
 
-	// if ( closedPath ) {
-	//
-	// 	points.push( points[ 0 ] );
-	//
-	// }
 
 
-	return points;
+				if ( tmpShape ) shapes.push( tmpShape );
 
 
-};
+				tmpShape = new THREE.Shape();
+				tmpShape.actions = tmpPath.actions;
+				tmpShape.curves = tmpPath.curves;
 
 
-/* Return an array of vectors based on contour of the path */
+			} else {
 
 
-THREE.Path.prototype.getPoints = function( divisions, closedPath ) {
+				tmpShape.holes.push( tmpPath );
+
+			}
+
+		}
+
+		shapes.push( tmpShape );
 
 
-	if (this.useSpacedPoints) {
-		console.log('tata');
-		return this.getSpacedPoints( divisions, closedPath );
 	}
 	}
 
 
-	divisions = divisions || 12;
+	//console.log("shape", shapes);
 
 
-	var points = [];
+	return shapes;
 
 
-	var i, il, item, action, args;
-	var cpx, cpy, cpx2, cpy2, cpx1, cpy1, cpx0, cpy0,
-		laste, j,
-		t, tx, ty;
+};
+/**
+ * @author zz85 / http://www.lab4games.net/zz85/blog
+ * Defines a 2d shape plane using paths.
+ **/
 
 
-	for ( i = 0, il = this.actions.length; i < il; i ++ ) {
+// STEP 1 Create a path.
+// STEP 2 Turn path into shape.
+// STEP 3 ExtrudeGeometry takes in Shape/Shapes
+// STEP 3a - Extract points from each shape, turn to vertices
+// STEP 3b - Triangulate each shape, add faces.
 
 
-		item = this.actions[ i ];
+THREE.Shape = function () {
 
 
-		action = item.action;
-		args = item.args;
+	THREE.Path.apply( this, arguments );
+	this.holes = [];
 
 
-		switch( action ) {
+};
 
 
-		case THREE.PathActions.MOVE_TO:
+THREE.Shape.prototype = Object.create( THREE.Path.prototype );
 
 
-			points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
+// Convenience method to return ExtrudeGeometry
 
 
-			break;
+THREE.Shape.prototype.extrude = function ( options ) {
 
 
-		case THREE.PathActions.LINE_TO:
+	var extruded = new THREE.ExtrudeGeometry( this, options );
+	return extruded;
 
 
-			points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
+};
 
 
-			break;
+// Convenience method to return ShapeGeometry
 
 
-		case THREE.PathActions.QUADRATIC_CURVE_TO:
+THREE.Shape.prototype.makeGeometry = function ( options ) {
 
 
-			cpx  = args[ 2 ];
-			cpy  = args[ 3 ];
+	var geometry = new THREE.ShapeGeometry( this, options );
+	return geometry;
 
 
-			cpx1 = args[ 0 ];
-			cpy1 = args[ 1 ];
+};
 
 
-			if ( points.length > 0 ) {
+// Get points of holes
 
 
-				laste = points[ points.length - 1 ];
+THREE.Shape.prototype.getPointsHoles = function ( divisions ) {
 
 
-				cpx0 = laste.x;
-				cpy0 = laste.y;
+	var i, il = this.holes.length, holesPts = [];
 
 
-			} else {
+	for ( i = 0; i < il; i ++ ) {
 
 
-				laste = this.actions[ i - 1 ].args;
+		holesPts[ i ] = this.holes[ i ].getTransformedPoints( divisions, this.bends );
 
 
-				cpx0 = laste[ laste.length - 2 ];
-				cpy0 = laste[ laste.length - 1 ];
+	}
 
 
-			}
+	return holesPts;
 
 
-			for ( j = 1; j <= divisions; j ++ ) {
+};
 
 
-				t = j / divisions;
+// Get points of holes (spaced by regular distance)
 
 
-				tx = THREE.Shape.Utils.b2( t, cpx0, cpx1, cpx );
-				ty = THREE.Shape.Utils.b2( t, cpy0, cpy1, cpy );
+THREE.Shape.prototype.getSpacedPointsHoles = function ( divisions ) {
 
 
-				points.push( new THREE.Vector2( tx, ty ) );
+	var i, il = this.holes.length, holesPts = [];
 
 
-		  	}
+	for ( i = 0; i < il; i ++ ) {
 
 
-			break;
+		holesPts[ i ] = this.holes[ i ].getTransformedSpacedPoints( divisions, this.bends );
 
 
-		case THREE.PathActions.BEZIER_CURVE_TO:
+	}
 
 
-			cpx  = args[ 4 ];
-			cpy  = args[ 5 ];
+	return holesPts;
 
 
-			cpx1 = args[ 0 ];
-			cpy1 = args[ 1 ];
+};
 
 
-			cpx2 = args[ 2 ];
-			cpy2 = args[ 3 ];
 
 
-			if ( points.length > 0 ) {
+// Get points of shape and holes (keypoints based on segments parameter)
 
 
-				laste = points[ points.length - 1 ];
+THREE.Shape.prototype.extractAllPoints = function ( divisions ) {
 
 
-				cpx0 = laste.x;
-				cpy0 = laste.y;
+	return {
 
 
-			} else {
+		shape: this.getTransformedPoints( divisions ),
+		holes: this.getPointsHoles( divisions )
 
 
-				laste = this.actions[ i - 1 ].args;
+	};
 
 
-				cpx0 = laste[ laste.length - 2 ];
-				cpy0 = laste[ laste.length - 1 ];
+};
 
 
-			}
+THREE.Shape.prototype.extractPoints = function ( divisions ) {
 
 
+	if (this.useSpacedPoints) {
+		return this.extractAllSpacedPoints(divisions);
+	}
 
 
-			for ( j = 1; j <= divisions; j ++ ) {
+	return this.extractAllPoints(divisions);
 
 
-				t = j / divisions;
+};
 
 
-				tx = THREE.Shape.Utils.b3( t, cpx0, cpx1, cpx2, cpx );
-				ty = THREE.Shape.Utils.b3( t, cpy0, cpy1, cpy2, cpy );
+//
+// THREE.Shape.prototype.extractAllPointsWithBend = function ( divisions, bend ) {
+//
+// 	return {
+//
+// 		shape: this.transform( bend, divisions ),
+// 		holes: this.getPointsHoles( divisions, bend )
+//
+// 	};
+//
+// };
 
 
-				points.push( new THREE.Vector2( tx, ty ) );
+// Get points of shape and holes (spaced by regular distance)
 
 
-			}
+THREE.Shape.prototype.extractAllSpacedPoints = function ( divisions ) {
 
 
-			break;
+	return {
 
 
-		case THREE.PathActions.CSPLINE_THRU:
+		shape: this.getTransformedSpacedPoints( divisions ),
+		holes: this.getSpacedPointsHoles( divisions )
 
 
-			laste = this.actions[ i - 1 ].args;
+	};
 
 
-			var last = new THREE.Vector2( laste[ laste.length - 2 ], laste[ laste.length - 1 ] );
-			var spts = [ last ];
+};
 
 
-			var n = divisions * args[ 0 ].length;
+/**************************************************************
+ *	Utils
+ **************************************************************/
 
 
-			spts = spts.concat( args[ 0 ] );
+THREE.Shape.Utils = {
 
 
-			var spline = new THREE.SplineCurve( spts );
+	/*
+		contour - array of vector2 for contour
+		holes   - array of array of vector2
+	*/
 
 
-			for ( j = 1; j <= n; j ++ ) {
+	removeHoles: function ( contour, holes ) {
 
 
-				points.push( spline.getPointAt( j / n ) ) ;
+		var shape = contour.concat(); // work on this shape
+		var allpoints = shape.concat();
 
 
-			}
+		/* For each isolated shape, find the closest points and break to the hole to allow triangulation */
 
 
-			break;
 
 
-		case THREE.PathActions.ARC:
+		var prevShapeVert, nextShapeVert,
+			prevHoleVert, nextHoleVert,
+			holeIndex, shapeIndex,
+			shapeId, shapeGroup,
+			h, h2,
+			hole, shortest, d,
+			p, pts1, pts2,
+			tmpShape1, tmpShape2,
+			tmpHole1, tmpHole2,
+			verts = [];
 
 
-			var aX = args[ 0 ], aY = args[ 1 ],
-				aRadius = args[ 2 ],
-				aStartAngle = args[ 3 ], aEndAngle = args[ 4 ],
-				aClockwise = !!args[ 5 ];
+		for ( h = 0; h < holes.length; h ++ ) {
 
 
-			var deltaAngle = aEndAngle - aStartAngle;
-			var angle;
-			var tdivisions = divisions * 2;
+			hole = holes[ h ];
 
 
-			for ( j = 1; j <= tdivisions; j ++ ) {
+			/*
+			shapeholes[ h ].concat(); // preserves original
+			holes.push( hole );
+			*/
 
 
-				t = j / tdivisions;
+			Array.prototype.push.apply( allpoints, hole );
 
 
-				if ( ! aClockwise ) {
+			shortest = Number.POSITIVE_INFINITY;
 
 
-					t = 1 - t;
 
 
-				}
+			// Find the shortest pair of pts between shape and hole
 
 
-				angle = aStartAngle + t * deltaAngle;
+			// Note: Actually, I'm not sure now if we could optimize this to be faster than O(m*n)
+			// Using distanceToSquared() intead of distanceTo() should speed a little
+			// since running square roots operations are reduced.
 
 
-				tx = aX + aRadius * Math.cos( angle );
-				ty = aY + aRadius * Math.sin( angle );
+			for ( h2 = 0; h2 < hole.length; h2 ++ ) {
 
 
-				//console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
+				pts1 = hole[ h2 ];
+				var dist = [];
 
 
-				points.push( new THREE.Vector2( tx, ty ) );
+				for ( p = 0; p < shape.length; p++ ) {
 
 
-			}
+					pts2 = shape[ p ];
+					d = pts1.distanceToSquared( pts2 );
+					dist.push( d );
 
 
-			//console.log(points);
+					if ( d < shortest ) {
 
 
-		  break;
-		  
-		case THREE.PathActions.ELLIPSE:
+						shortest = d;
+						holeIndex = h2;
+						shapeIndex = p;
 
 
-			var aX = args[ 0 ], aY = args[ 1 ],
-				xRadius = args[ 2 ],
-				yRadius = args[ 3 ],
-				aStartAngle = args[ 4 ], aEndAngle = args[ 5 ],
-				aClockwise = !!args[ 6 ];
+					}
 
 
+				}
 
 
-			var deltaAngle = aEndAngle - aStartAngle;
-			var angle;
-			var tdivisions = divisions * 2;
+			}
 
 
-			for ( j = 1; j <= tdivisions; j ++ ) {
+			//console.log("shortest", shortest, dist);
 
 
-				t = j / tdivisions;
+			prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
+			prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
 
 
-				if ( ! aClockwise ) {
+			var areaapts = [
 
 
-					t = 1 - t;
+				hole[ holeIndex ],
+				shape[ shapeIndex ],
+				shape[ prevShapeVert ]
 
 
-				}
+			];
 
 
-				angle = aStartAngle + t * deltaAngle;
+			var areaa = THREE.FontUtils.Triangulate.area( areaapts );
 
 
-				tx = aX + xRadius * Math.cos( angle );
-				ty = aY + yRadius * Math.sin( angle );
+			var areabpts = [
 
 
-				//console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
+				hole[ holeIndex ],
+				hole[ prevHoleVert ],
+				shape[ shapeIndex ]
 
 
-				points.push( new THREE.Vector2( tx, ty ) );
+			];
 
 
-			}
+			var areab = THREE.FontUtils.Triangulate.area( areabpts );
 
 
-			//console.log(points);
+			var shapeOffset = 1;
+			var holeOffset = -1;
 
 
-		  break;
+			var oldShapeIndex = shapeIndex, oldHoleIndex = holeIndex;
+			shapeIndex += shapeOffset;
+			holeIndex += holeOffset;
 
 
-		} // end switch
+			if ( shapeIndex < 0 ) { shapeIndex += shape.length;  }
+			shapeIndex %= shape.length;
 
 
-	}
+			if ( holeIndex < 0 ) { holeIndex += hole.length;  }
+			holeIndex %= hole.length;
 
 
+			prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
+			prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
 
 
+			areaapts = [
 
 
-	// Normalize to remove the closing point by default.
-	var lastPoint = points[ points.length - 1];
-	var EPSILON = 0.0000000001;
-	if ( Math.abs(lastPoint.x - points[ 0 ].x) < EPSILON &&
-             Math.abs(lastPoint.y - points[ 0 ].y) < EPSILON)
-		points.splice( points.length - 1, 1);
-	if ( closedPath ) {
+				hole[ holeIndex ],
+				shape[ shapeIndex ],
+				shape[ prevShapeVert ]
 
 
-		points.push( points[ 0 ] );
+			];
 
 
-	}
+			var areaa2 = THREE.FontUtils.Triangulate.area( areaapts );
 
 
-	return points;
+			areabpts = [
 
 
-};
+				hole[ holeIndex ],
+				hole[ prevHoleVert ],
+				shape[ shapeIndex ]
 
 
-// Breaks path into shapes
+			];
 
 
-THREE.Path.prototype.toShapes = function() {
+			var areab2 = THREE.FontUtils.Triangulate.area( areabpts );
+			//console.log(areaa,areab ,areaa2,areab2, ( areaa + areab ),  ( areaa2 + areab2 ));
 
 
-	var i, il, item, action, args;
+			if ( ( areaa + areab ) > ( areaa2 + areab2 ) ) {
 
 
-	var subPaths = [], lastPath = new THREE.Path();
+				// In case areas are not correct.
+				//console.log("USE THIS");
 
 
-	for ( i = 0, il = this.actions.length; i < il; i ++ ) {
+				shapeIndex = oldShapeIndex;
+				holeIndex = oldHoleIndex ;
 
 
-		item = this.actions[ i ];
+				if ( shapeIndex < 0 ) { shapeIndex += shape.length;  }
+				shapeIndex %= shape.length;
 
 
-		args = item.args;
-		action = item.action;
+				if ( holeIndex < 0 ) { holeIndex += hole.length;  }
+				holeIndex %= hole.length;
 
 
-		if ( action == THREE.PathActions.MOVE_TO ) {
+				prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
+				prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
 
 
-			if ( lastPath.actions.length != 0 ) {
+			} else {
 
 
-				subPaths.push( lastPath );
-				lastPath = new THREE.Path();
+				//console.log("USE THAT ")
 
 
 			}
 			}
 
 
-		}
+			tmpShape1 = shape.slice( 0, shapeIndex );
+			tmpShape2 = shape.slice( shapeIndex );
+			tmpHole1 = hole.slice( holeIndex );
+			tmpHole2 = hole.slice( 0, holeIndex );
 
 
-		lastPath[ action ].apply( lastPath, args );
+			// Should check orders here again?
 
 
-	}
+			var trianglea = [
 
 
-	if ( lastPath.actions.length != 0 ) {
+				hole[ holeIndex ],
+				shape[ shapeIndex ],
+				shape[ prevShapeVert ]
 
 
-		subPaths.push( lastPath );
+			];
 
 
-	}
+			var triangleb = [
 
 
-	// console.log(subPaths);
+				hole[ holeIndex ] ,
+				hole[ prevHoleVert ],
+				shape[ shapeIndex ]
 
 
-	if ( subPaths.length == 0 ) return [];
+			];
 
 
-	var tmpPath, tmpShape, shapes = [];
+			verts.push( trianglea );
+			verts.push( triangleb );
 
 
-	var holesFirst = !THREE.Shape.Utils.isClockWise( subPaths[ 0 ].getPoints() );
-	// console.log("Holes first", holesFirst);
+			shape = tmpShape1.concat( tmpHole1 ).concat( tmpHole2 ).concat( tmpShape2 );
 
 
-	if ( subPaths.length == 1) {
-		tmpPath = subPaths[0];
-		tmpShape = new THREE.Shape();
-		tmpShape.actions = tmpPath.actions;
-		tmpShape.curves = tmpPath.curves;
-		shapes.push( tmpShape );
-		return shapes;
-	};
+		}
 
 
-	if ( holesFirst ) {
+		return {
 
 
-		tmpShape = new THREE.Shape();
+			shape:shape, 		/* shape with no holes */
+			isolatedPts: verts, /* isolated faces */
+			allpoints: allpoints
 
 
-		for ( i = 0, il = subPaths.length; i < il; i ++ ) {
+		}
 
 
-			tmpPath = subPaths[ i ];
 
 
-			if ( THREE.Shape.Utils.isClockWise( tmpPath.getPoints() ) ) {
+	},
 
 
-				tmpShape.actions = tmpPath.actions;
-				tmpShape.curves = tmpPath.curves;
+	triangulateShape: function ( contour, holes ) {
 
 
-				shapes.push( tmpShape );
-				tmpShape = new THREE.Shape();
+		var shapeWithoutHoles = THREE.Shape.Utils.removeHoles( contour, holes );
 
 
-				//console.log('cw', i);
+		var shape = shapeWithoutHoles.shape,
+			allpoints = shapeWithoutHoles.allpoints,
+			isolatedPts = shapeWithoutHoles.isolatedPts;
 
 
-			} else {
+		var triangles = THREE.FontUtils.Triangulate( shape, false ); // True returns indices for points of spooled shape
 
 
-				tmpShape.holes.push( tmpPath );
+		// To maintain reference to old shape, one must match coordinates, or offset the indices from original arrays. It's probably easier to do the first.
 
 
-				//console.log('ccw', i);
+		//console.log( "triangles",triangles, triangles.length );
+		//console.log( "allpoints",allpoints, allpoints.length );
 
 
-			}
+		var i, il, f, face,
+			key, index,
+			allPointsMap = {},
+			isolatedPointsMap = {};
 
 
-		}
+		// prepare all points map
 
 
-	} else {
+		for ( i = 0, il = allpoints.length; i < il; i ++ ) {
 
 
-		// Shapes first
+			key = allpoints[ i ].x + ":" + allpoints[ i ].y;
 
 
-		for ( i = 0, il = subPaths.length; i < il; i ++ ) {
+			if ( allPointsMap[ key ] !== undefined ) {
 
 
-			tmpPath = subPaths[ i ];
+				console.log( "Duplicate point", key );
 
 
-			if ( THREE.Shape.Utils.isClockWise( tmpPath.getPoints() ) ) {
+			}
 
 
+			allPointsMap[ key ] = i;
 
 
-				if ( tmpShape ) shapes.push( tmpShape );
+		}
 
 
-				tmpShape = new THREE.Shape();
-				tmpShape.actions = tmpPath.actions;
-				tmpShape.curves = tmpPath.curves;
+		// check all face vertices against all points map
 
 
-			} else {
+		for ( i = 0, il = triangles.length; i < il; i ++ ) {
 
 
-				tmpShape.holes.push( tmpPath );
+			face = triangles[ i ];
 
 
-			}
+			for ( f = 0; f < 3; f ++ ) {
 
 
-		}
+				key = face[ f ].x + ":" + face[ f ].y;
 
 
-		shapes.push( tmpShape );
+				index = allPointsMap[ key ];
 
 
-	}
+				if ( index !== undefined ) {
 
 
-	//console.log("shape", shapes);
+					face[ f ] = index;
 
 
-	return shapes;
+				}
 
 
-};
-/**
- * @author zz85 / http://www.lab4games.net/zz85/blog
- * Defines a 2d shape plane using paths.
- **/
+			}
 
 
-// STEP 1 Create a path.
-// STEP 2 Turn path into shape.
-// STEP 3 ExtrudeGeometry takes in Shape/Shapes
-// STEP 3a - Extract points from each shape, turn to vertices
-// STEP 3b - Triangulate each shape, add faces.
+		}
 
 
-THREE.Shape = function () {
+		// check isolated points vertices against all points map
 
 
-	THREE.Path.apply( this, arguments );
-	this.holes = [];
+		for ( i = 0, il = isolatedPts.length; i < il; i ++ ) {
 
 
-};
+			face = isolatedPts[ i ];
 
 
-THREE.Shape.prototype = Object.create( THREE.Path.prototype );
+			for ( f = 0; f < 3; f ++ ) {
 
 
-// Convenience method to return ExtrudeGeometry
+				key = face[ f ].x + ":" + face[ f ].y;
 
 
-THREE.Shape.prototype.extrude = function ( options ) {
+				index = allPointsMap[ key ];
 
 
-	var extruded = new THREE.ExtrudeGeometry( this, options );
-	return extruded;
+				if ( index !== undefined ) {
 
 
-};
+					face[ f ] = index;
 
 
-// Convenience method to return ShapeGeometry
+				}
 
 
-THREE.Shape.prototype.makeGeometry = function ( options ) {
+			}
 
 
-	var geometry = new THREE.ShapeGeometry( this, options );
-	return geometry;
+		}
 
 
-};
+		return triangles.concat( isolatedPts );
 
 
-// Get points of holes
+	}, // end triangulate shapes
 
 
-THREE.Shape.prototype.getPointsHoles = function ( divisions ) {
+	/*
+	triangulate2 : function( pts, holes ) {
 
 
-	var i, il = this.holes.length, holesPts = [];
+		// For use with Poly2Tri.js
 
 
-	for ( i = 0; i < il; i ++ ) {
+		var allpts = pts.concat();
+		var shape = [];
+		for (var p in pts) {
+			shape.push(new js.poly2tri.Point(pts[p].x, pts[p].y));
+		}
 
 
-		holesPts[ i ] = this.holes[ i ].getTransformedPoints( divisions, this.bends );
+		var swctx = new js.poly2tri.SweepContext(shape);
 
 
-	}
+		for (var h in holes) {
+			var aHole = holes[h];
+			var newHole = []
+			for (i in aHole) {
+				newHole.push(new js.poly2tri.Point(aHole[i].x, aHole[i].y));
+				allpts.push(aHole[i]);
+			}
+			swctx.AddHole(newHole);
+		}
 
 
-	return holesPts;
+		var find;
+		var findIndexForPt = function (pt) {
+			find = new THREE.Vector2(pt.x, pt.y);
+			var p;
+			for (p=0, pl = allpts.length; p<pl; p++) {
+				if (allpts[p].equals(find)) return p;
+			}
+			return -1;
+		};
 
 
-};
+		// triangulate
+		js.poly2tri.sweep.Triangulate(swctx);
 
 
-// Get points of holes (spaced by regular distance)
+		var triangles =  swctx.GetTriangles();
+		var tr ;
+		var facesPts = [];
+		for (var t in triangles) {
+			tr =  triangles[t];
+			facesPts.push([
+				findIndexForPt(tr.GetPoint(0)),
+				findIndexForPt(tr.GetPoint(1)),
+				findIndexForPt(tr.GetPoint(2))
+					]);
+		}
 
 
-THREE.Shape.prototype.getSpacedPointsHoles = function ( divisions ) {
 
 
-	var i, il = this.holes.length, holesPts = [];
+	//	console.log(facesPts);
+	//	console.log("triangles", triangles.length, triangles);
 
 
-	for ( i = 0; i < il; i ++ ) {
+		// Returns array of faces with 3 element each
+	return facesPts;
+	},
+*/
 
 
-		holesPts[ i ] = this.holes[ i ].getTransformedSpacedPoints( divisions, this.bends );
+	isClockWise: function ( pts ) {
 
 
-	}
+		return THREE.FontUtils.Triangulate.area( pts ) < 0;
 
 
-	return holesPts;
+	},
 
 
-};
+	// Bezier Curves formulas obtained from
+	// http://en.wikipedia.org/wiki/B%C3%A9zier_curve
 
 
+	// Quad Bezier Functions
 
 
-// Get points of shape and holes (keypoints based on segments parameter)
+	b2p0: function ( t, p ) {
 
 
-THREE.Shape.prototype.extractAllPoints = function ( divisions ) {
+		var k = 1 - t;
+		return k * k * p;
 
 
-	return {
+	},
 
 
-		shape: this.getTransformedPoints( divisions ),
-		holes: this.getPointsHoles( divisions )
+	b2p1: function ( t, p ) {
 
 
-	};
+		return 2 * ( 1 - t ) * t * p;
 
 
-};
+	},
 
 
-THREE.Shape.prototype.extractPoints = function ( divisions ) {
+	b2p2: function ( t, p ) {
 
 
-	if (this.useSpacedPoints) {
-		return this.extractAllSpacedPoints(divisions);
-	}
+		return t * t * p;
 
 
-	return this.extractAllPoints(divisions);
+	},
 
 
-};
+	b2: function ( t, p0, p1, p2 ) {
 
 
-//
-// THREE.Shape.prototype.extractAllPointsWithBend = function ( divisions, bend ) {
-//
-// 	return {
-//
-// 		shape: this.transform( bend, divisions ),
-// 		holes: this.getPointsHoles( divisions, bend )
-//
-// 	};
-//
-// };
+		return this.b2p0( t, p0 ) + this.b2p1( t, p1 ) + this.b2p2( t, p2 );
+
+	},
 
 
-// Get points of shape and holes (spaced by regular distance)
+	// Cubic Bezier Functions
 
 
-THREE.Shape.prototype.extractAllSpacedPoints = function ( divisions ) {
+	b3p0: function ( t, p ) {
 
 
-	return {
+		var k = 1 - t;
+		return k * k * k * p;
 
 
-		shape: this.getTransformedSpacedPoints( divisions ),
-		holes: this.getSpacedPointsHoles( divisions )
+	},
 
 
-	};
+	b3p1: function ( t, p ) {
 
 
-};
+		var k = 1 - t;
+		return 3 * k * k * t * p;
 
 
-/**************************************************************
- *	Utils
- **************************************************************/
+	},
 
 
-THREE.Shape.Utils = {
+	b3p2: function ( t, p ) {
 
 
-	/*
-		contour - array of vector2 for contour
-		holes   - array of array of vector2
-	*/
+		var k = 1 - t;
+		return 3 * k * t * t * p;
 
 
-	removeHoles: function ( contour, holes ) {
+	},
 
 
-		var shape = contour.concat(); // work on this shape
-		var allpoints = shape.concat();
+	b3p3: function ( t, p ) {
 
 
-		/* For each isolated shape, find the closest points and break to the hole to allow triangulation */
+		return t * t * t * p;
 
 
+	},
 
 
-		var prevShapeVert, nextShapeVert,
-			prevHoleVert, nextHoleVert,
-			holeIndex, shapeIndex,
-			shapeId, shapeGroup,
-			h, h2,
-			hole, shortest, d,
-			p, pts1, pts2,
-			tmpShape1, tmpShape2,
-			tmpHole1, tmpHole2,
-			verts = [];
+	b3: function ( t, p0, p1, p2, p3 ) {
 
 
-		for ( h = 0; h < holes.length; h ++ ) {
+		return this.b3p0( t, p0 ) + this.b3p1( t, p1 ) + this.b3p2( t, p2 ) +  this.b3p3( t, p3 );
 
 
-			hole = holes[ h ];
+	}
 
 
-			/*
-			shapeholes[ h ].concat(); // preserves original
-			holes.push( hole );
-			*/
+};
 
 
-			Array.prototype.push.apply( allpoints, hole );
+/**************************************************************
+ *	Line
+ **************************************************************/
 
 
-			shortest = Number.POSITIVE_INFINITY;
+THREE.LineCurve = function ( v1, v2 ) {
 
 
+	this.v1 = v1;
+	this.v2 = v2;
 
 
-			// Find the shortest pair of pts between shape and hole
+};
 
 
-			// Note: Actually, I'm not sure now if we could optimize this to be faster than O(m*n)
-			// Using distanceToSquared() intead of distanceTo() should speed a little
-			// since running square roots operations are reduced.
+THREE.LineCurve.prototype = Object.create( THREE.Curve.prototype );
 
 
-			for ( h2 = 0; h2 < hole.length; h2 ++ ) {
+THREE.LineCurve.prototype.getPoint = function ( t ) {
 
 
-				pts1 = hole[ h2 ];
-				var dist = [];
+	var point = this.v2.clone().sub(this.v1);
+	point.multiplyScalar( t ).add( this.v1 );
 
 
-				for ( p = 0; p < shape.length; p++ ) {
+	return point;
 
 
-					pts2 = shape[ p ];
-					d = pts1.distanceToSquared( pts2 );
-					dist.push( d );
+};
 
 
-					if ( d < shortest ) {
+// Line curve is linear, so we can overwrite default getPointAt
 
 
-						shortest = d;
-						holeIndex = h2;
-						shapeIndex = p;
+THREE.LineCurve.prototype.getPointAt = function ( u ) {
 
 
-					}
+	return this.getPoint( u );
 
 
-				}
+};
 
 
-			}
+THREE.LineCurve.prototype.getTangent = function( t ) {
 
 
-			//console.log("shortest", shortest, dist);
+	var tangent = this.v2.clone().sub(this.v1);
 
 
-			prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
-			prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
+	return tangent.normalize();
 
 
-			var areaapts = [
+};/**************************************************************
+ *	Quadratic Bezier curve
+ **************************************************************/
 
 
-				hole[ holeIndex ],
-				shape[ shapeIndex ],
-				shape[ prevShapeVert ]
 
 
-			];
+THREE.QuadraticBezierCurve = function ( v0, v1, v2 ) {
 
 
-			var areaa = THREE.FontUtils.Triangulate.area( areaapts );
+	this.v0 = v0;
+	this.v1 = v1;
+	this.v2 = v2;
 
 
-			var areabpts = [
+};
 
 
-				hole[ holeIndex ],
-				hole[ prevHoleVert ],
-				shape[ shapeIndex ]
+THREE.QuadraticBezierCurve.prototype = Object.create( THREE.Curve.prototype );
 
 
-			];
 
 
-			var areab = THREE.FontUtils.Triangulate.area( areabpts );
+THREE.QuadraticBezierCurve.prototype.getPoint = function ( t ) {
 
 
-			var shapeOffset = 1;
-			var holeOffset = -1;
+	var tx, ty;
 
 
-			var oldShapeIndex = shapeIndex, oldHoleIndex = holeIndex;
-			shapeIndex += shapeOffset;
-			holeIndex += holeOffset;
+	tx = THREE.Shape.Utils.b2( t, this.v0.x, this.v1.x, this.v2.x );
+	ty = THREE.Shape.Utils.b2( t, this.v0.y, this.v1.y, this.v2.y );
 
 
-			if ( shapeIndex < 0 ) { shapeIndex += shape.length;  }
-			shapeIndex %= shape.length;
+	return new THREE.Vector2( tx, ty );
 
 
-			if ( holeIndex < 0 ) { holeIndex += hole.length;  }
-			holeIndex %= hole.length;
+};
 
 
-			prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
-			prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
 
 
-			areaapts = [
+THREE.QuadraticBezierCurve.prototype.getTangent = function( t ) {
 
 
-				hole[ holeIndex ],
-				shape[ shapeIndex ],
-				shape[ prevShapeVert ]
+	var tx, ty;
 
 
-			];
+	tx = THREE.Curve.Utils.tangentQuadraticBezier( t, this.v0.x, this.v1.x, this.v2.x );
+	ty = THREE.Curve.Utils.tangentQuadraticBezier( t, this.v0.y, this.v1.y, this.v2.y );
 
 
-			var areaa2 = THREE.FontUtils.Triangulate.area( areaapts );
+	// returns unit vector
 
 
-			areabpts = [
+	var tangent = new THREE.Vector2( tx, ty );
+	tangent.normalize();
 
 
-				hole[ holeIndex ],
-				hole[ prevHoleVert ],
-				shape[ shapeIndex ]
+	return tangent;
 
 
-			];
+};/**************************************************************
+ *	Cubic Bezier curve
+ **************************************************************/
 
 
-			var areab2 = THREE.FontUtils.Triangulate.area( areabpts );
-			//console.log(areaa,areab ,areaa2,areab2, ( areaa + areab ),  ( areaa2 + areab2 ));
+THREE.CubicBezierCurve = function ( v0, v1, v2, v3 ) {
 
 
-			if ( ( areaa + areab ) > ( areaa2 + areab2 ) ) {
+	this.v0 = v0;
+	this.v1 = v1;
+	this.v2 = v2;
+	this.v3 = v3;
 
 
-				// In case areas are not correct.
-				//console.log("USE THIS");
+};
 
 
-				shapeIndex = oldShapeIndex;
-				holeIndex = oldHoleIndex ;
+THREE.CubicBezierCurve.prototype = Object.create( THREE.Curve.prototype );
 
 
-				if ( shapeIndex < 0 ) { shapeIndex += shape.length;  }
-				shapeIndex %= shape.length;
+THREE.CubicBezierCurve.prototype.getPoint = function ( t ) {
 
 
-				if ( holeIndex < 0 ) { holeIndex += hole.length;  }
-				holeIndex %= hole.length;
+	var tx, ty;
 
 
-				prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
-				prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
+	tx = THREE.Shape.Utils.b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
+	ty = THREE.Shape.Utils.b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
 
 
-			} else {
+	return new THREE.Vector2( tx, ty );
 
 
-				//console.log("USE THAT ")
+};
 
 
-			}
+THREE.CubicBezierCurve.prototype.getTangent = function( t ) {
 
 
-			tmpShape1 = shape.slice( 0, shapeIndex );
-			tmpShape2 = shape.slice( shapeIndex );
-			tmpHole1 = hole.slice( holeIndex );
-			tmpHole2 = hole.slice( 0, holeIndex );
+	var tx, ty;
 
 
-			// Should check orders here again?
+	tx = THREE.Curve.Utils.tangentCubicBezier( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
+	ty = THREE.Curve.Utils.tangentCubicBezier( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
 
 
-			var trianglea = [
+	var tangent = new THREE.Vector2( tx, ty );
+	tangent.normalize();
 
 
-				hole[ holeIndex ],
-				shape[ shapeIndex ],
-				shape[ prevShapeVert ]
+	return tangent;
 
 
-			];
+};/**************************************************************
+ *	Spline curve
+ **************************************************************/
 
 
-			var triangleb = [
+THREE.SplineCurve = function ( points /* array of Vector2 */ ) {
 
 
-				hole[ holeIndex ] ,
-				hole[ prevHoleVert ],
-				shape[ shapeIndex ]
+	this.points = (points == undefined) ? [] : points;
 
 
-			];
+};
 
 
-			verts.push( trianglea );
-			verts.push( triangleb );
+THREE.SplineCurve.prototype = Object.create( THREE.Curve.prototype );
 
 
-			shape = tmpShape1.concat( tmpHole1 ).concat( tmpHole2 ).concat( tmpShape2 );
+THREE.SplineCurve.prototype.getPoint = function ( t ) {
 
 
-		}
+	var v = new THREE.Vector2();
+	var c = [];
+	var points = this.points, point, intPoint, weight;
+	point = ( points.length - 1 ) * t;
 
 
-		return {
+	intPoint = Math.floor( point );
+	weight = point - intPoint;
 
 
-			shape:shape, 		/* shape with no holes */
-			isolatedPts: verts, /* isolated faces */
-			allpoints: allpoints
+	c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
+	c[ 1 ] = intPoint;
+	c[ 2 ] = intPoint  > points.length - 2 ? points.length -1 : intPoint + 1;
+	c[ 3 ] = intPoint  > points.length - 3 ? points.length -1 : intPoint + 2;
 
 
-		}
+	v.x = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight );
+	v.y = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight );
 
 
+	return v;
 
 
-	},
+};/**************************************************************
+ *	Ellipse curve
+ **************************************************************/
 
 
-	triangulateShape: function ( contour, holes ) {
+THREE.EllipseCurve = function ( aX, aY, xRadius, yRadius,
+							aStartAngle, aEndAngle,
+							aClockwise ) {
 
 
-		var shapeWithoutHoles = THREE.Shape.Utils.removeHoles( contour, holes );
+	this.aX = aX;
+	this.aY = aY;
 
 
-		var shape = shapeWithoutHoles.shape,
-			allpoints = shapeWithoutHoles.allpoints,
-			isolatedPts = shapeWithoutHoles.isolatedPts;
+	this.xRadius = xRadius;
+	this.yRadius = yRadius;
 
 
-		var triangles = THREE.FontUtils.Triangulate( shape, false ); // True returns indices for points of spooled shape
+	this.aStartAngle = aStartAngle;
+	this.aEndAngle = aEndAngle;
 
 
-		// To maintain reference to old shape, one must match coordinates, or offset the indices from original arrays. It's probably easier to do the first.
+	this.aClockwise = aClockwise;
 
 
-		//console.log( "triangles",triangles, triangles.length );
-		//console.log( "allpoints",allpoints, allpoints.length );
+};
 
 
-		var i, il, f, face,
-			key, index,
-			allPointsMap = {},
-			isolatedPointsMap = {};
+THREE.EllipseCurve.prototype = Object.create( THREE.Curve.prototype );
 
 
-		// prepare all points map
+THREE.EllipseCurve.prototype.getPoint = function ( t ) {
 
 
-		for ( i = 0, il = allpoints.length; i < il; i ++ ) {
+	var deltaAngle = this.aEndAngle - this.aStartAngle;
 
 
-			key = allpoints[ i ].x + ":" + allpoints[ i ].y;
+	if ( !this.aClockwise ) {
 
 
-			if ( allPointsMap[ key ] !== undefined ) {
+		t = 1 - t;
 
 
-				console.log( "Duplicate point", key );
+	}
 
 
-			}
+	var angle = this.aStartAngle + t * deltaAngle;
 
 
-			allPointsMap[ key ] = i;
+	var tx = this.aX + this.xRadius * Math.cos( angle );
+	var ty = this.aY + this.yRadius * Math.sin( angle );
 
 
-		}
+	return new THREE.Vector2( tx, ty );
 
 
-		// check all face vertices against all points map
+};/**************************************************************
+ *	Arc curve
+ **************************************************************/
 
 
-		for ( i = 0, il = triangles.length; i < il; i ++ ) {
+THREE.ArcCurve = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
 
 
-			face = triangles[ i ];
+	THREE.EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
+};
 
 
-			for ( f = 0; f < 3; f ++ ) {
+THREE.ArcCurve.prototype = Object.create( THREE.EllipseCurve.prototype );/**************************************************************
+ *	Line3D
+ **************************************************************/
 
 
-				key = face[ f ].x + ":" + face[ f ].y;
+THREE.LineCurve3 = THREE.Curve.create(
 
 
-				index = allPointsMap[ key ];
+	function ( v1, v2 ) {
 
 
-				if ( index !== undefined ) {
+		this.v1 = v1;
+		this.v2 = v2;
 
 
-					face[ f ] = index;
+	},
 
 
-				}
+	function ( t ) {
 
 
-			}
+		var r = new THREE.Vector3();
 
 
-		}
 
 
-		// check isolated points vertices against all points map
+		r.subVectors( this.v2, this.v1 ); // diff
+		r.multiplyScalar( t );
+		r.add( this.v1 );
 
 
-		for ( i = 0, il = isolatedPts.length; i < il; i ++ ) {
+		return r;
 
 
-			face = isolatedPts[ i ];
+	}
 
 
-			for ( f = 0; f < 3; f ++ ) {
+);
+/**************************************************************
+ *	Quadratic Bezier 3D curve
+ **************************************************************/
 
 
-				key = face[ f ].x + ":" + face[ f ].y;
+THREE.QuadraticBezierCurve3 = THREE.Curve.create(
 
 
-				index = allPointsMap[ key ];
+	function ( v0, v1, v2 ) {
 
 
-				if ( index !== undefined ) {
+		this.v0 = v0;
+		this.v1 = v1;
+		this.v2 = v2;
 
 
-					face[ f ] = index;
+	},
 
 
-				}
+	function ( t ) {
 
 
-			}
+		var tx, ty, tz;
 
 
-		}
+		tx = THREE.Shape.Utils.b2( t, this.v0.x, this.v1.x, this.v2.x );
+		ty = THREE.Shape.Utils.b2( t, this.v0.y, this.v1.y, this.v2.y );
+		tz = THREE.Shape.Utils.b2( t, this.v0.z, this.v1.z, this.v2.z );
 
 
-		return triangles.concat( isolatedPts );
+		return new THREE.Vector3( tx, ty, tz );
 
 
-	}, // end triangulate shapes
+	}
 
 
-	/*
-	triangulate2 : function( pts, holes ) {
+);/**************************************************************
+ *	Cubic Bezier 3D curve
+ **************************************************************/
 
 
-		// For use with Poly2Tri.js
+THREE.CubicBezierCurve3 = THREE.Curve.create(
 
 
-		var allpts = pts.concat();
-		var shape = [];
-		for (var p in pts) {
-			shape.push(new js.poly2tri.Point(pts[p].x, pts[p].y));
-		}
+	function ( v0, v1, v2, v3 ) {
 
 
-		var swctx = new js.poly2tri.SweepContext(shape);
+		this.v0 = v0;
+		this.v1 = v1;
+		this.v2 = v2;
+		this.v3 = v3;
 
 
-		for (var h in holes) {
-			var aHole = holes[h];
-			var newHole = []
-			for (i in aHole) {
-				newHole.push(new js.poly2tri.Point(aHole[i].x, aHole[i].y));
-				allpts.push(aHole[i]);
-			}
-			swctx.AddHole(newHole);
-		}
+	},
 
 
-		var find;
-		var findIndexForPt = function (pt) {
-			find = new THREE.Vector2(pt.x, pt.y);
-			var p;
-			for (p=0, pl = allpts.length; p<pl; p++) {
-				if (allpts[p].equals(find)) return p;
-			}
-			return -1;
-		};
+	function ( t ) {
 
 
-		// triangulate
-		js.poly2tri.sweep.Triangulate(swctx);
+		var tx, ty, tz;
 
 
-		var triangles =  swctx.GetTriangles();
-		var tr ;
-		var facesPts = [];
-		for (var t in triangles) {
-			tr =  triangles[t];
-			facesPts.push([
-				findIndexForPt(tr.GetPoint(0)),
-				findIndexForPt(tr.GetPoint(1)),
-				findIndexForPt(tr.GetPoint(2))
-					]);
-		}
+		tx = THREE.Shape.Utils.b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
+		ty = THREE.Shape.Utils.b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
+		tz = THREE.Shape.Utils.b3( t, this.v0.z, this.v1.z, this.v2.z, this.v3.z );
 
 
+		return new THREE.Vector3( tx, ty, tz );
 
 
-	//	console.log(facesPts);
-	//	console.log("triangles", triangles.length, triangles);
+	}
 
 
-		// Returns array of faces with 3 element each
-	return facesPts;
-	},
-*/
+);/**************************************************************
+ *	Spline 3D curve
+ **************************************************************/
 
 
-	isClockWise: function ( pts ) {
 
 
-		return THREE.FontUtils.Triangulate.area( pts ) < 0;
+THREE.SplineCurve3 = THREE.Curve.create(
 
 
-	},
+	function ( points /* array of Vector3 */) {
 
 
-	// Bezier Curves formulas obtained from
-	// http://en.wikipedia.org/wiki/B%C3%A9zier_curve
+		this.points = (points == undefined) ? [] : points;
 
 
-	// Quad Bezier Functions
+	},
 
 
-	b2p0: function ( t, p ) {
+	function ( t ) {
 
 
-		var k = 1 - t;
-		return k * k * p;
+		var v = new THREE.Vector3();
+		var c = [];
+		var points = this.points, point, intPoint, weight;
+		point = ( points.length - 1 ) * t;
 
 
-	},
+		intPoint = Math.floor( point );
+		weight = point - intPoint;
 
 
-	b2p1: function ( t, p ) {
+		c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
+		c[ 1 ] = intPoint;
+		c[ 2 ] = intPoint  > points.length - 2 ? points.length - 1 : intPoint + 1;
+		c[ 3 ] = intPoint  > points.length - 3 ? points.length - 1 : intPoint + 2;
 
 
-		return 2 * ( 1 - t ) * t * p;
+		var pt0 = points[ c[0] ],
+			pt1 = points[ c[1] ],
+			pt2 = points[ c[2] ],
+			pt3 = points[ c[3] ];
 
 
-	},
+		v.x = THREE.Curve.Utils.interpolate(pt0.x, pt1.x, pt2.x, pt3.x, weight);
+		v.y = THREE.Curve.Utils.interpolate(pt0.y, pt1.y, pt2.y, pt3.y, weight);
+		v.z = THREE.Curve.Utils.interpolate(pt0.z, pt1.z, pt2.z, pt3.z, weight);
 
 
-	b2p2: function ( t, p ) {
+		return v;
 
 
-		return t * t * p;
+	}
 
 
-	},
+);
 
 
-	b2: function ( t, p0, p1, p2 ) {
 
 
-		return this.b2p0( t, p0 ) + this.b2p1( t, p1 ) + this.b2p2( t, p2 );
+// THREE.SplineCurve3.prototype.getTangent = function(t) {
+// 		var v = new THREE.Vector3();
+// 		var c = [];
+// 		var points = this.points, point, intPoint, weight;
+// 		point = ( points.length - 1 ) * t;
 
 
-	},
+// 		intPoint = Math.floor( point );
+// 		weight = point - intPoint;
 
 
-	// Cubic Bezier Functions
+// 		c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
+// 		c[ 1 ] = intPoint;
+// 		c[ 2 ] = intPoint  > points.length - 2 ? points.length - 1 : intPoint + 1;
+// 		c[ 3 ] = intPoint  > points.length - 3 ? points.length - 1 : intPoint + 2;
 
 
-	b3p0: function ( t, p ) {
+// 		var pt0 = points[ c[0] ],
+// 			pt1 = points[ c[1] ],
+// 			pt2 = points[ c[2] ],
+// 			pt3 = points[ c[3] ];
 
 
-		var k = 1 - t;
-		return k * k * k * p;
+// 	// t = weight;
+// 	v.x = THREE.Curve.Utils.tangentSpline( t, pt0.x, pt1.x, pt2.x, pt3.x );
+// 	v.y = THREE.Curve.Utils.tangentSpline( t, pt0.y, pt1.y, pt2.y, pt3.y );
+// 	v.z = THREE.Curve.Utils.tangentSpline( t, pt0.z, pt1.z, pt2.z, pt3.z );
 
 
-	},
+// 	return v;
 
 
-	b3p1: function ( t, p ) {
+// }/**************************************************************
+ *	Closed Spline 3D curve
+ **************************************************************/
 
 
-		var k = 1 - t;
-		return 3 * k * k * t * p;
 
 
-	},
+THREE.ClosedSplineCurve3 = THREE.Curve.create(
 
 
-	b3p2: function ( t, p ) {
+	function ( points /* array of Vector3 */) {
 
 
-		var k = 1 - t;
-		return 3 * k * t * t * p;
+		this.points = (points == undefined) ? [] : points;
 
 
 	},
 	},
 
 
-	b3p3: function ( t, p ) {
+    function ( t ) {
 
 
-		return t * t * t * p;
+        var v = new THREE.Vector3();
+        var c = [];
+        var points = this.points, point, intPoint, weight;
+        point = ( points.length - 0 ) * t;
+            // This needs to be from 0-length +1
 
 
-	},
+        intPoint = Math.floor( point );
+        weight = point - intPoint;
 
 
-	b3: function ( t, p0, p1, p2, p3 ) {
+        intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / points.length ) + 1 ) * points.length;
+        c[ 0 ] = ( intPoint - 1 ) % points.length;
+        c[ 1 ] = ( intPoint ) % points.length;
+        c[ 2 ] = ( intPoint + 1 ) % points.length;
+        c[ 3 ] = ( intPoint + 2 ) % points.length;
 
 
-		return this.b3p0( t, p0 ) + this.b3p1( t, p1 ) + this.b3p2( t, p2 ) +  this.b3p3( t, p3 );
+        v.x = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight );
+        v.y = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight );
+        v.z = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].z, points[ c[ 1 ] ].z, points[ c[ 2 ] ].z, points[ c[ 3 ] ].z, weight );
 
 
-	}
+        return v;
 
 
-};
+    }
 
 
-/**
+);/**
  * @author mikael emtinger / http://gomo.se/
  * @author mikael emtinger / http://gomo.se/
  */
  */
 
 

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 4 - 14
build/three.min.js


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio