Browse Source

Merge branch 'dev' into Plane_applyMatrix4

Greg Tatum 11 years ago
parent
commit
e4c393fcd8

+ 2 - 2
docs/api/math/Frustum.html

@@ -61,7 +61,7 @@
 		p5 -- [page:Plane]
 		p5 -- [page:Plane]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Sets the current frustum from the passed planes. No plane order is implicitely implied.
 		</div>
 		</div>
 
 
 		<h3>.copy([page:Frustum frustum]) [page:Frustum this]</h3>
 		<h3>.copy([page:Frustum frustum]) [page:Frustum this]</h3>
@@ -69,7 +69,7 @@
 		frustum -- The frustum to copy
 		frustum -- The frustum to copy
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Copies the values of the passed frustum.
 		</div>
 		</div>
 
 
 		<h3>.containsPoint([page:Vector3 point]) [page:Boolean]</h3>
 		<h3>.containsPoint([page:Vector3 point]) [page:Boolean]</h3>

+ 3 - 3
docs/api/math/Line3.html

@@ -2,9 +2,9 @@
 <html lang="en">
 <html lang="en">
 	<head>
 	<head>
 		<meta charset="utf-8" />
 		<meta charset="utf-8" />
-		<script src="../../../list.js"></script>
-		<script src="../../../page.js"></script>
-		<link type="text/css" rel="stylesheet" href="../../../page.css" />
+		<script src="../../list.js"></script>
+		<script src="../../page.js"></script>
+		<link type="text/css" rel="stylesheet" href="../../page.css" />
 	</head>
 	</head>
 	<body>
 	<body>
 		<h1>[name]</h1>
 		<h1>[name]</h1>

+ 72 - 76
docs/api/math/Plane.html

@@ -9,181 +9,177 @@
 	<body>
 	<body>
 		<h1>[name]</h1>
 		<h1>[name]</h1>
 
 
-		<div class="desc">todo</div>
+		<div class="desc">A two dimensional surface that extends infinitely in 3d space.</div>
 
 
 
 
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
 
 
-		<h3>[name]([page:Vector3 normal], [page:number constant])</h3>
+		<h3>[name]([page:Vector3 normal], [page:Float constant])</h3>
 		<div>
 		<div>
-		normal -- the normal vector defining the plane <br />
-		constant -- the distance from the origin to the plane along the normal vector
+		normal -- ([Page:Vector3]) normal vector defining the plane pointing towards the origin <br />
+		constant -- ([Page:Float]) the negative distance from the origin to the plane along the normal vector
 		</div>
 		</div>
 
 
 
 
 		<h2>Properties</h2>
 		<h2>Properties</h2>
 
 
-
-
-		<h3>.[page:number constant]</h3>
-		<div>
-		the distance from the origin to the plane along the normal vector
-		</div> 
-
 		<h3>.[page:Vector3 normal]</h3>
 		<h3>.[page:Vector3 normal]</h3>
-		<div>
-		the normal vector defining the plane
-		</div> 
 
 
+		<h3>.[page:Float constant]</h3>
+		
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 
 
 
 
 
 
-		<h3>.normalize() [page:todo]</h3>
+		<h3>.normalize() [page:Plane this]</h3>
 		<div>
 		<div>
-		todo
+		Normalizes the normal vector, and adjusts the constant value accordingly.
 		</div>
 		</div>
 
 
-		<h3>.set([page:todo normal], [page:todo constant]) [page:todo]</h3>
+		<h3>.set([page:Vector3 normal], [page:Float constant]) [page:Plane this]</h3>
 		<div>
 		<div>
-		normal -- todo <br />
-		constant -- todo
+		normal -- [Page:Vector3] <br />
+		constant -- [Page:Float]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Sets the plane's values.
 		</div>
 		</div>
 
 
-		<h3>.copy([page:todo plane]) [page:todo]</h3>
+		<h3>.copy([page:Plane plane]) [page:Plane this]</h3>
 		<div>
 		<div>
-		plane -- todo
+		plane -- [page:Plane] to copy
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Copies the values of the passed plane to this plane.
 		</div>
 		</div>
 
 
-		<h3>.applyMatrix4([page:todo matrix], [page:todo optionalNormalMatrix]) [page:todo]</h3>
+		<h3>.applyMatrix4([page:Matrix4 matrix], [page:Matrix3 optionalNormalMatrix]) [page:Plane this]</h3>
 		<div>
 		<div>
-		matrix -- todo <br />
-		optionalNormalMatrix -- todo
+		matrix -- [Page:Matrix4] to apply <br />
+		optionalNormalMatrix -- (optional) normal [Page:Matrix3] of the Matrix4 to apply
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Apply a Matrix4 to the plane. The second parameter is optional, but if not provided a new Matrix3 will be created each time this method is called.
+		
+		<code>
+		var optionalNormalMatrix = new THREE.Matrix3().getNormalMatrix( matrix ) 
+		</code>
 		</div>
 		</div>
 
 
-		<h3>.orthoPoint([page:todo point], [page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.orthoPoint([page:Vector3 point], [page:Vector3 optionalTarget]) [page:Vector3]</h3>
 		<div>
 		<div>
-		point -- todo <br />
-		optionalTarget -- todo
+		point -- [page:Vector3] <br />
+		optionalTarget -- [page:Vector3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns a vector in the same direction as the Plane's normal, but the magnitude is passed point's original distance to the plane.
 		</div>
 		</div>
 
 
-		<h3>.isIntersectionLine([page:todo line]) [page:todo]</h3>
+		<h3>.isIntersectionLine([page:Line3 line]) [page:Boolean]</h3>
 		<div>
 		<div>
-		line -- todo
+		line -- [page:Line3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Tests whether a line segment intersects with the plane. (Do not mistake this for a collinear check.)
 		</div>
 		</div>
 
 
-		<h3>.intersectLine([page:todo line], [page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.intersectLine([page:Line3 line], [page:Vector3 optionalTarget]) [page:Vector3] or [page:undefined]</h3>
 		<div>
 		<div>
-		line -- todo <br />
-		optionalTarget -- todo
+		line -- [page:Line3] <br />
+		optionalTarget -- [page:Vector3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns the intersection point of the passed line and the plane. Returns undefined if the line does not intersect. Returns the line's starting point if the line is coplanar with the plane.
 		</div>
 		</div>
 
 
-		<h3>.setFromNormalAndCoplanarPoint([page:todo normal], [page:todo point]) [page:todo]</h3>
+		<h3>.setFromNormalAndCoplanarPoint([page:Vector3 normal], [page:Vector3 point]) [page:Vector3 this]</h3>
 		<div>
 		<div>
-		normal -- todo <br />
-		point -- todo
+		normal -- [page:Vector3] <br />
+		point -- [page:Vector3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Sets the plane's values as defined by a normal and arbitrary coplanar point.
 		</div>
 		</div>
 
 
-		<h3>.clone() [page:todo]</h3>
+		<h3>.clone() [page:Plane]</h3>
 		<div>
 		<div>
-		todo
+		Returns a new copy of this plane.
 		</div>
 		</div>
 
 
-		<h3>.distanceToPoint([page:todo point]) [page:todo]</h3>
+		<h3>.distanceToPoint([page:Vector3 point]) [page:Float]</h3>
 		<div>
 		<div>
-		point -- todo
+		point -- [page:Vector3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns the smallest distance from the point to the plane.
 		</div>
 		</div>
 
 
-		<h3>.equals([page:todo plane]) [page:todo]</h3>
+		<h3>.equals([page:Plane plane]) [page:Boolean]</h3>
 		<div>
 		<div>
-		plane -- todo
+		plane -- [page:Planen]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Checks to see if two planes are equal (their normals and constants match)
 		</div>
 		</div>
 
 
-		<h3>.setComponents([page:todo x], [page:todo y], [page:todo z], [page:todo w]) [page:todo]</h3>
+		<h3>.setComponents([page:Float x], [page:Float y], [page:Float z], [page:Float w]) [page:Plane this]</h3>
 		<div>
 		<div>
-		x -- todo <br />
-		y -- todo <br />
-		z -- todo <br />
-		w -- todo
+		x -- [page:Float] x of the normal vector <br />
+		y -- [page:Float] y of the normal vector<br />
+		z -- [page:Float] z of the normal vector<br />
+		w -- [page:Float] distance of the plane from the origin along the normal vector
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Set the individual components that make up the plane.
 		</div>
 		</div>
 
 
-		<h3>.distanceToSphere([page:todo sphere]) [page:todo]</h3>
+		<h3>.distanceToSphere([page:Sphere sphere]) [page:Float]</h3>
 		<div>
 		<div>
-		sphere -- todo
+		sphere -- [Page:Sphere]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns the smallest distance from an edge of the sphere to the plane.
 		</div>
 		</div>
 
 
-		<h3>.setFromCoplanarPoints([page:todo a], [page:todo b], [page:todo c]) [page:todo]</h3>
+		<h3>.setFromCoplanarPoints([page:Vector3 a], [page:Vector3 b], [page:Vector3 c]) [page:Plane this]</h3>
 		<div>
 		<div>
-		a -- todo <br />
-		b -- todo <br />
-		c -- todo
+		a -- [page:Vector3] <br />
+		b -- [page:Vector3] <br />
+		c -- [page:Vector3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Defines the plane based on the 3 provided points. The winding order is counter clockwise, and determines which direction the normal will point.
 		</div>
 		</div>
 
 
-		<h3>.projectPoint([page:todo point], [page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.projectPoint([page:Vector3 point], [page:Vector3 optionalTarget]) [page:Vector3]</h3>
 		<div>
 		<div>
-		point -- todo <br />
-		optionalTarget -- todo
+		point -- [page:Vector3] <br />
+		optionalTarget -- [page:Vector3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Projects a point onto the plane. The projected point is the closest point on the plane to the passed point, so a line drawn from the projected point and the passed point would be orthogonal to the plane.
 		</div>
 		</div>
 
 
-		<h3>.negate() [page:todo]</h3>
+		<h3>.negate() [page:Plane this]</h3>
 		<div>
 		<div>
-		todo
+		Negates both the normal vector and constant, effectively mirroring the plane across the origin.
 		</div>
 		</div>
 
 
-		<h3>.translate([page:todo offset]) [page:todo]</h3>
+		<h3>.translate([page:Vector3 offset]) [page:Plane this]</h3>
 		<div>
 		<div>
-		offset -- todo
+		offset -- [page:Vector3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Translates the plane the distance defined by the vector. Note that this only affects the constant (distance from origin) and will not affect the normal vector.
 		</div>
 		</div>
 
 
-		<h3>.coplanarPoint([page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.coplanarPoint([page:Vector3 optionalTarget]) [page:Vector3]</h3>
 		<div>
 		<div>
-		optionalTarget -- todo
+		optionalTarget -- [page:Vector3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns a coplanar point. (The projection of the normal vector at the origin onto the plane.)
 		</div>
 		</div>
 
 
 		<h2>Source</h2>
 		<h2>Source</h2>

+ 1 - 0
docs/list.js

@@ -75,6 +75,7 @@ var list = {
 			[ "Color", "api/math/Color" ],
 			[ "Color", "api/math/Color" ],
 			[ "Euler", "api/math/Euler" ],
 			[ "Euler", "api/math/Euler" ],
 			[ "Frustum", "api/math/Frustum" ],
 			[ "Frustum", "api/math/Frustum" ],
+			[ "Line3", "api/math/Line3" ],
 			[ "Math", "api/math/Math" ],
 			[ "Math", "api/math/Math" ],
 			[ "Matrix3", "api/math/Matrix3" ],
 			[ "Matrix3", "api/math/Matrix3" ],
 			[ "Matrix4", "api/math/Matrix4" ],
 			[ "Matrix4", "api/math/Matrix4" ],

+ 2 - 2
examples/canvas_interactive_cubes.html

@@ -78,7 +78,7 @@
 					program: function ( context ) {
 					program: function ( context ) {
 
 
 						context.beginPath();
 						context.beginPath();
-						context.arc( 0, 0, 1, 0, PI2, true );
+						context.arc( 0, 0, 0.5, 0, PI2, true );
 						context.fill();
 						context.fill();
 
 
 					}
 					}
@@ -131,7 +131,7 @@
 
 
 					var particle = new THREE.Sprite( particleMaterial );
 					var particle = new THREE.Sprite( particleMaterial );
 					particle.position = intersects[ 0 ].point;
 					particle.position = intersects[ 0 ].point;
-					particle.scale.x = particle.scale.y = 8;
+					particle.scale.x = particle.scale.y = 16;
 					scene.add( particle );
 					scene.add( particle );
 
 
 				}
 				}

+ 2 - 2
examples/canvas_interactive_lines.html

@@ -53,7 +53,7 @@
 				var program = function ( context ) {
 				var program = function ( context ) {
 
 
 					context.beginPath();
 					context.beginPath();
-					context.arc( 0, 0, 1, 0, PI2, true );
+					context.arc( 0, 0, 0.5, 0, PI2, true );
 					context.fill();
 					context.fill();
 
 
 				}
 				}
@@ -64,7 +64,7 @@
 						program: program }
 						program: program }
 					)
 					)
 				);
 				);
-				sphereInter.scale.x = sphereInter.scale.y = 5;
+				sphereInter.scale.x = sphereInter.scale.y = 10;
 				sphereInter.visible = false;
 				sphereInter.visible = false;
 				scene.add( sphereInter );
 				scene.add( sphereInter );
 
 

+ 4 - 4
examples/canvas_interactive_particles.html

@@ -29,16 +29,16 @@
 			var programFill = function ( context ) {
 			var programFill = function ( context ) {
 
 
 				context.beginPath();
 				context.beginPath();
-				context.arc( 0, 0, 1, 0, PI2, true );
+				context.arc( 0, 0, 0.5, 0, PI2, true );
 				context.fill();
 				context.fill();
 
 
 			}
 			}
 
 
 			var programStroke = function ( context ) {
 			var programStroke = function ( context ) {
 
 
-				context.lineWidth = 0.05;
+				context.lineWidth = 0.025;
 				context.beginPath();
 				context.beginPath();
-				context.arc( 0, 0, 1, 0, PI2, true );
+				context.arc( 0, 0, 0.5, 0, PI2, true );
 				context.stroke();
 				context.stroke();
 
 
 			}
 			}
@@ -72,7 +72,7 @@
 					particle.position.x = Math.random() * 800 - 400;
 					particle.position.x = Math.random() * 800 - 400;
 					particle.position.y = Math.random() * 800 - 400;
 					particle.position.y = Math.random() * 800 - 400;
 					particle.position.z = Math.random() * 800 - 400;
 					particle.position.z = Math.random() * 800 - 400;
-					particle.scale.x = particle.scale.y = Math.random() * 10 + 10;
+					particle.scale.x = particle.scale.y = Math.random() * 20 + 20;
 					scene.add( particle );
 					scene.add( particle );
 
 
 				}
 				}

+ 1 - 4
examples/canvas_lights_pointlights.html

@@ -75,21 +75,18 @@
 				var program = function ( context ) {
 				var program = function ( context ) {
 
 
 					context.beginPath();
 					context.beginPath();
-					context.arc( 0, 0, 1, 0, PI2, true );
+					context.arc( 0, 0, 0.5, 0, PI2, true );
 					context.fill();
 					context.fill();
 
 
 				}
 				}
 
 
 				particle1 = new THREE.Sprite( new THREE.SpriteCanvasMaterial( { color: 0xff0040, program: program } ) );
 				particle1 = new THREE.Sprite( new THREE.SpriteCanvasMaterial( { color: 0xff0040, program: program } ) );
-				particle1.scale.x = particle1.scale.y = particle1.scale.z = 0.5;
 				scene.add( particle1 );
 				scene.add( particle1 );
 
 
 				particle2 = new THREE.Sprite( new THREE.SpriteCanvasMaterial( { color: 0x0040ff, program: program } ) );
 				particle2 = new THREE.Sprite( new THREE.SpriteCanvasMaterial( { color: 0x0040ff, program: program } ) );
-				particle2.scale.x = particle2.scale.y = particle2.scale.z = 0.5;
 				scene.add( particle2 );
 				scene.add( particle2 );
 
 
 				particle3 = new THREE.Sprite( new THREE.SpriteCanvasMaterial( { color: 0x80ff80, program: program } ) );
 				particle3 = new THREE.Sprite( new THREE.SpriteCanvasMaterial( { color: 0x80ff80, program: program } ) );
-				particle3.scale.x = particle3.scale.y = particle3.scale.z = 0.5;
 				scene.add( particle3 );
 				scene.add( particle3 );
 
 
 				loader = new THREE.JSONLoader();
 				loader = new THREE.JSONLoader();

+ 1 - 4
examples/canvas_lights_pointlights_smooth.html

@@ -75,21 +75,18 @@
 				var program = function ( context ) {
 				var program = function ( context ) {
 
 
 					context.beginPath();
 					context.beginPath();
-					context.arc( 0, 0, 1, 0, PI2, true );
+					context.arc( 0, 0, 0.5, 0, PI2, true );
 					context.fill();
 					context.fill();
 
 
 				}
 				}
 
 
 				particle1 = new THREE.Sprite( new THREE.SpriteCanvasMaterial( { color: 0xff0040, program: program } ) );
 				particle1 = new THREE.Sprite( new THREE.SpriteCanvasMaterial( { color: 0xff0040, program: program } ) );
-				particle1.scale.x = particle1.scale.y = particle1.scale.z = 0.5;
 				scene.add( particle1 );
 				scene.add( particle1 );
 
 
 				particle2 = new THREE.Sprite( new THREE.SpriteCanvasMaterial( { color: 0x0040ff, program: program } ) );
 				particle2 = new THREE.Sprite( new THREE.SpriteCanvasMaterial( { color: 0x0040ff, program: program } ) );
-				particle2.scale.x = particle2.scale.y = particle2.scale.z = 0.5;
 				scene.add( particle2 );
 				scene.add( particle2 );
 
 
 				particle3 = new THREE.Sprite( new THREE.SpriteCanvasMaterial( { color: 0x80ff80, program: program } ) );
 				particle3 = new THREE.Sprite( new THREE.SpriteCanvasMaterial( { color: 0x80ff80, program: program } ) );
-				particle3.scale.x = particle3.scale.y = particle3.scale.z = 0.5;
 				scene.add( particle3 );
 				scene.add( particle3 );
 
 
 				loader = new THREE.JSONLoader();
 				loader = new THREE.JSONLoader();

+ 2 - 2
examples/canvas_lines.html

@@ -62,7 +62,7 @@
 					program: function ( context ) {
 					program: function ( context ) {
 
 
 						context.beginPath();
 						context.beginPath();
-						context.arc( 0, 0, 1, 0, PI2, true );
+						context.arc( 0, 0, 0.5, 0, PI2, true );
 						context.fill();
 						context.fill();
 
 
 					}
 					}
@@ -79,7 +79,7 @@
 					particle.position.z = Math.random() * 2 - 1;
 					particle.position.z = Math.random() * 2 - 1;
 					particle.position.normalize();
 					particle.position.normalize();
 					particle.position.multiplyScalar( Math.random() * 10 + 450 );
 					particle.position.multiplyScalar( Math.random() * 10 + 450 );
-					particle.scale.x = particle.scale.y = 5;
+					particle.scale.x = particle.scale.y = 10;
 					scene.add( particle );
 					scene.add( particle );
 
 
 					geometry.vertices.push( particle.position );
 					geometry.vertices.push( particle.position );

+ 2 - 2
examples/canvas_materials.html

@@ -111,13 +111,13 @@
 				var program = function ( context ) {
 				var program = function ( context ) {
 
 
 					context.beginPath();
 					context.beginPath();
-					context.arc( 0, 0, 1, 0, PI2, true );
+					context.arc( 0, 0, 0.5, 0, PI2, true );
 					context.fill();
 					context.fill();
 
 
 				}
 				}
 
 
 				particleLight = new THREE.Sprite( new THREE.SpriteCanvasMaterial( { color: 0xffffff, program: program } ) );
 				particleLight = new THREE.Sprite( new THREE.SpriteCanvasMaterial( { color: 0xffffff, program: program } ) );
-				particleLight.scale.x = particleLight.scale.y = particleLight.scale.z = 4;
+				particleLight.scale.x = particleLight.scale.y = 8;
 				scene.add( particleLight );
 				scene.add( particleLight );
 
 
 				// Lights
 				// Lights

+ 2 - 1
examples/canvas_materials_video.html

@@ -128,7 +128,7 @@
 					program: function ( context ) {
 					program: function ( context ) {
 
 
 						context.beginPath();
 						context.beginPath();
-						context.arc( 0, 0, 1, 0, PI2, true );
+						context.arc( 0, 0, 0.5, 0, PI2, true );
 						context.fill();
 						context.fill();
 
 
 					}
 					}
@@ -143,6 +143,7 @@
 						particle.position.x = ix * separation - ( ( amountx * separation ) / 2 );
 						particle.position.x = ix * separation - ( ( amountx * separation ) / 2 );
 						particle.position.y = -153
 						particle.position.y = -153
 						particle.position.z = iy * separation - ( ( amounty * separation ) / 2 );
 						particle.position.z = iy * separation - ( ( amounty * separation ) / 2 );
+						particle.scale.x = particle.scale.y = 2;
 						scene.add( particle );
 						scene.add( particle );
 
 
 					}
 					}

+ 2 - 1
examples/index.html

@@ -127,6 +127,7 @@
 				"webgl_geometry_cube",
 				"webgl_geometry_cube",
 				"webgl_geometry_dynamic",
 				"webgl_geometry_dynamic",
 				"webgl_geometry_extrude_shapes",
 				"webgl_geometry_extrude_shapes",
+				"webgl_geometry_extrude_shapes2",
 				"webgl_geometry_extrude_splines",
 				"webgl_geometry_extrude_splines",
 				"webgl_geometry_extrude_uvs2",
 				"webgl_geometry_extrude_uvs2",
 				"webgl_geometry_hierarchy",
 				"webgl_geometry_hierarchy",
@@ -408,4 +409,4 @@
 		</script>
 		</script>
 
 
 	</body>
 	</body>
-</html>
+</html>

+ 90 - 69
examples/js/controls/TrackballControls.js

@@ -1,5 +1,6 @@
 /**
 /**
  * @author Eberhard Graether / http://egraether.com/
  * @author Eberhard Graether / http://egraether.com/
+ * @author Mark Lundin 		 / http://mark-lundin.com
  */
  */
 
 
 THREE.TrackballControls = function ( object, domElement ) {
 THREE.TrackballControls = function ( object, domElement ) {
@@ -98,89 +99,102 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 
 	};
 	};
 
 
-	this.getMouseOnScreen = function ( clientX, clientY ) {
+	this.getMouseOnScreen = function ( clientX, clientY, optionalTarget ) {
 
 
-		return new THREE.Vector2(
+		return ( optionalTarget || new THREE.Vector2() ).set(
 			( clientX - _this.screen.left ) / _this.screen.width,
 			( clientX - _this.screen.left ) / _this.screen.width,
 			( clientY - _this.screen.top ) / _this.screen.height
 			( clientY - _this.screen.top ) / _this.screen.height
 		);
 		);
 
 
 	};
 	};
 
 
-	this.getMouseProjectionOnBall = function ( clientX, clientY ) {
+	this.getMouseProjectionOnBall = (function(){
 
 
-		var mouseOnBall = new THREE.Vector3(
-			( clientX - _this.screen.width * 0.5 - _this.screen.left ) / (_this.screen.width*.5),
-			( _this.screen.height * 0.5 + _this.screen.top - clientY ) / (_this.screen.height*.5),
-			0.0
-		);
 
 
-		var length = mouseOnBall.length();
+		var objectUp = new THREE.Vector3();
 
 
-		if ( _this.noRoll ) {
 
 
-			if ( length < Math.SQRT1_2 ) {
+		return function ( clientX, clientY, projection ) {
 
 
-				mouseOnBall.z = Math.sqrt( 1.0 - length*length );
+			var mouseOnBall = new THREE.Vector3(
+				( clientX - _this.screen.width * 0.5 - _this.screen.left ) / (_this.screen.width*.5),
+				( _this.screen.height * 0.5 + _this.screen.top - clientY ) / (_this.screen.height*.5),
+				0.0
+			);
 
 
-			} else {
+			var length = mouseOnBall.length();
 
 
-				mouseOnBall.z = .5 / length;
-				
-			}
+			if ( _this.noRoll ) {
 
 
-		} else if ( length > 1.0 ) {
+				if ( length < Math.SQRT1_2 ) {
 
 
-			mouseOnBall.normalize();
+					mouseOnBall.z = Math.sqrt( 1.0 - length*length );
 
 
-		} else {
+				} else {
+
+					mouseOnBall.z = .5 / length;
+					
+				}
+
+			} else if ( length > 1.0 ) {
 
 
-			mouseOnBall.z = Math.sqrt( 1.0 - length * length );
+				mouseOnBall.normalize();
 
 
+			} else {
+
+				mouseOnBall.z = Math.sqrt( 1.0 - length * length );
+
+			}
+
+			_eye.copy( _this.object.position ).sub( _this.target );
+
+			projection.copy( _this.object.up ).setLength( mouseOnBall.y )
+			projection.add( objectUp.copy( _this.object.up ).cross( _eye ).setLength( mouseOnBall.x ) );
+			projection.add( _eye.setLength( mouseOnBall.z ) );
+
+			return projection;
 		}
 		}
 
 
-		_eye.copy( _this.object.position ).sub( _this.target );
+	}());
 
 
-		var projection = _this.object.up.clone().setLength( mouseOnBall.y );
-		projection.add( _this.object.up.clone().cross( _eye ).setLength( mouseOnBall.x ) );
-		projection.add( _eye.setLength( mouseOnBall.z ) );
+	this.rotateCamera = (function(){
 
 
-		return projection;
+		var axis = new THREE.Vector3(),
+			quaternion = new THREE.Quaternion();
 
 
-	};
 
 
-	this.rotateCamera = function () {
+		return function () {
 
 
-		var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );
+			var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );
 
 
-		if ( angle ) {
+			if ( angle ) {
 
 
-			var axis = ( new THREE.Vector3() ).crossVectors( _rotateStart, _rotateEnd ).normalize(),
-				quaternion = new THREE.Quaternion();
+				axis.crossVectors( _rotateStart, _rotateEnd ).normalize();
 
 
-			angle *= _this.rotateSpeed;
+				angle *= _this.rotateSpeed;
 
 
-			quaternion.setFromAxisAngle( axis, -angle );
+				quaternion.setFromAxisAngle( axis, -angle );
 
 
-			_eye.applyQuaternion( quaternion );
-			_this.object.up.applyQuaternion( quaternion );
+				_eye.applyQuaternion( quaternion );
+				_this.object.up.applyQuaternion( quaternion );
 
 
-			_rotateEnd.applyQuaternion( quaternion );
+				_rotateEnd.applyQuaternion( quaternion );
 
 
-			if ( _this.staticMoving ) {
+				if ( _this.staticMoving ) {
 
 
-				_rotateStart.copy( _rotateEnd );
+					_rotateStart.copy( _rotateEnd );
 
 
-			} else {
+				} else {
 
 
-				quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) );
-				_rotateStart.applyQuaternion( quaternion );
+					quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) );
+					_rotateStart.applyQuaternion( quaternion );
 
 
-			}
+				}
 
 
+			}
 		}
 		}
 
 
-	};
+	}());
 
 
 	this.zoomCamera = function () {
 	this.zoomCamera = function () {
 
 
@@ -214,33 +228,40 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 
 	};
 	};
 
 
-	this.panCamera = function () {
+	this.panCamera = (function(){
 
 
-		var mouseChange = _panEnd.clone().sub( _panStart );
+		var mouseChange = new THREE.Vector2(),
+			objectUp = new THREE.Vector3(),
+			pan = new THREE.Vector3();
 
 
-		if ( mouseChange.lengthSq() ) {
+		return function () {
 
 
-			mouseChange.multiplyScalar( _eye.length() * _this.panSpeed );
+			mouseChange.copy( _panEnd ).sub( _panStart );
 
 
-			var pan = _eye.clone().cross( _this.object.up ).setLength( mouseChange.x );
-			pan.add( _this.object.up.clone().setLength( mouseChange.y ) );
+			if ( mouseChange.lengthSq() ) {
 
 
-			_this.object.position.add( pan );
-			_this.target.add( pan );
+				mouseChange.multiplyScalar( _eye.length() * _this.panSpeed );
 
 
-			if ( _this.staticMoving ) {
+				pan.copy( _eye ).cross( _this.object.up ).setLength( mouseChange.x );
+				pan.add( objectUp.copy( _this.object.up ).setLength( mouseChange.y ) );
 
 
-				_panStart = _panEnd;
+				_this.object.position.add( pan );
+				_this.target.add( pan );
 
 
-			} else {
+				if ( _this.staticMoving ) {
 
 
-				_panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
+					_panStart.copy( _panEnd );
 
 
-			}
+				} else {
+
+					_panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
 
 
+				}
+
+			}
 		}
 		}
 
 
-	};
+	}());
 
 
 	this.checkDistances = function () {
 	this.checkDistances = function () {
 
 
@@ -374,17 +395,17 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 
 		if ( _state === STATE.ROTATE && !_this.noRotate ) {
 		if ( _state === STATE.ROTATE && !_this.noRotate ) {
 
 
-			_rotateStart = _this.getMouseProjectionOnBall( event.clientX, event.clientY );
+			_rotateStart = _this.getMouseProjectionOnBall( event.clientX, event.clientY, _rotateStart );
 			_rotateEnd.copy(_rotateStart)
 			_rotateEnd.copy(_rotateStart)
 
 
 		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
 		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
 
 
-			_zoomStart = _this.getMouseOnScreen( event.clientX, event.clientY );
+			_zoomStart = _this.getMouseOnScreen( event.clientX, event.clientY, _zoomStart );
 			_zoomEnd.copy(_zoomStart);
 			_zoomEnd.copy(_zoomStart);
 
 
 		} else if ( _state === STATE.PAN && !_this.noPan ) {
 		} else if ( _state === STATE.PAN && !_this.noPan ) {
 
 
-			_panStart = _this.getMouseOnScreen( event.clientX, event.clientY );
+			_panStart = _this.getMouseOnScreen( event.clientX, event.clientY, _panStart);
 			_panEnd.copy(_panStart)
 			_panEnd.copy(_panStart)
 
 
 		}
 		}
@@ -405,15 +426,15 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 
 		if ( _state === STATE.ROTATE && !_this.noRotate ) {
 		if ( _state === STATE.ROTATE && !_this.noRotate ) {
 
 
-			_rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY );
+			_rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY, _rotateEnd );
 
 
 		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
 		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
 
 
-			_zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
+			_zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY, _zoomEnd );
 
 
 		} else if ( _state === STATE.PAN && !_this.noPan ) {
 		} else if ( _state === STATE.PAN && !_this.noPan ) {
 
 
-			_panEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
+			_panEnd = _this.getMouseOnScreen( event.clientX, event.clientY, _panEnd );
 
 
 		}
 		}
 
 
@@ -467,7 +488,7 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 
 			case 1:
 			case 1:
 				_state = STATE.TOUCH_ROTATE;
 				_state = STATE.TOUCH_ROTATE;
-				_rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				_rotateEnd.copy( _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, _rotateStart ));
 				break;
 				break;
 
 
 			case 2:
 			case 2:
@@ -479,7 +500,7 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 
 			case 3:
 			case 3:
 				_state = STATE.TOUCH_PAN;
 				_state = STATE.TOUCH_PAN;
-				_panStart = _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				_panEnd.copy( _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, _panStart ));
 				break;
 				break;
 
 
 			default:
 			default:
@@ -501,7 +522,7 @@ THREE.TrackballControls = function ( object, domElement ) {
 		switch ( event.touches.length ) {
 		switch ( event.touches.length ) {
 
 
 			case 1:
 			case 1:
-				_rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				_rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, _rotateEnd );
 				break;
 				break;
 
 
 			case 2:
 			case 2:
@@ -511,7 +532,7 @@ THREE.TrackballControls = function ( object, domElement ) {
 				break;
 				break;
 
 
 			case 3:
 			case 3:
-				_panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				_panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, _panEnd );
 				break;
 				break;
 
 
 			default:
 			default:
@@ -528,7 +549,7 @@ THREE.TrackballControls = function ( object, domElement ) {
 		switch ( event.touches.length ) {
 		switch ( event.touches.length ) {
 
 
 			case 1:
 			case 1:
-				_rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				_rotateStart.copy( _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, _rotateEnd ));
 				break;
 				break;
 
 
 			case 2:
 			case 2:
@@ -536,7 +557,7 @@ THREE.TrackballControls = function ( object, domElement ) {
 				break;
 				break;
 
 
 			case 3:
 			case 3:
-				_panStart = _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				_panStart.copy( _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, _panEnd ));
 				break;
 				break;
 
 
 		}
 		}

+ 2 - 0
examples/js/loaders/ColladaLoader.js

@@ -1101,6 +1101,7 @@ THREE.ColladaLoader = function () {
 		}
 		}
 
 
 		obj.name = node.name || node.id || "";
 		obj.name = node.name || node.id || "";
+		obj.layer = node.layer || "";
 		obj.matrix = node.matrix;
 		obj.matrix = node.matrix;
 		obj.matrix.decompose( obj.position, obj.quaternion, obj.scale );
 		obj.matrix.decompose( obj.position, obj.quaternion, obj.scale );
 
 
@@ -2060,6 +2061,7 @@ THREE.ColladaLoader = function () {
 		this.sid = element.getAttribute('sid');
 		this.sid = element.getAttribute('sid');
 		this.name = element.getAttribute('name');
 		this.name = element.getAttribute('name');
 		this.type = element.getAttribute('type');
 		this.type = element.getAttribute('type');
+		this.layer = element.getAttribute('layer');
 
 
 		this.type = this.type == 'JOINT' ? this.type : 'NODE';
 		this.type = this.type == 'JOINT' ? this.type : 'NODE';
 
 

+ 427 - 419
examples/webgl_geometry_extrude_shapes2.html

@@ -6,10 +6,10 @@
 <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 <style>
 <style>
 body {
 body {
-    font-family: Monospace;
-    background-color: #f0f0f0;
-    margin: 0px;
-    overflow: hidden;
+	font-family: Monospace;
+	background-color: #f0f0f0;
+	margin: 0px;
+	overflow: hidden;
 }
 }
 </style>
 </style>
 </head>
 </head>
@@ -25,7 +25,8 @@ body {
 
 
 
 
 
 
-<script type="text/javascript" src="../build/three.js"></script>
+<script type="text/javascript" src="../build/three.min.js"></script>
+<script src="js/libs/stats.min.js"></script>
 
 
 
 
 
 
@@ -37,234 +38,233 @@ body {
 
 
 function d3threeD(exports) {
 function d3threeD(exports) {
 
 
-const DEGS_TO_RADS = Math.PI / 180,
-      UNIT_SIZE = 100;
+const DEGS_TO_RADS = Math.PI / 180, UNIT_SIZE = 100;
+
+const DIGIT_0 = 48, DIGIT_9 = 57, COMMA = 44, SPACE = 32, PERIOD = 46, MINUS = 45;
 
 
-const DIGIT_0 = 48, DIGIT_9 = 57, COMMA = 44, SPACE = 32, PERIOD = 46,
-      MINUS = 45;
 exports.transformSVGPath =
 exports.transformSVGPath =
 function transformSVGPath(pathStr) {
 function transformSVGPath(pathStr) {
-  var path = new THREE.Shape();
-
-  var idx = 1, len = pathStr.length, activeCmd,
-      x = 0, y = 0, nx = 0, ny = 0, firstX = null, firstY = null,
-      x1 = 0, x2 = 0, y1 = 0, y2 = 0,
-      rx = 0, ry = 0, xar = 0, laf = 0, sf = 0, cx, cy;
-
-  function eatNum() {
-    var sidx, c, isFloat = false, s;
-    // eat delims
-    while (idx < len) {
-      c = pathStr.charCodeAt(idx);
-      if (c !== COMMA && c !== SPACE)
-        break;
-      idx++;
-    }
-    if (c === MINUS)
-      sidx = idx++;
-    else
-      sidx = idx;
-    // eat number
-    while (idx < len) {
-      c = pathStr.charCodeAt(idx);
-      if (DIGIT_0 <= c && c <= DIGIT_9) {
-        idx++;
-        continue;
-      }
-      else if (c === PERIOD) {
-        idx++;
-        isFloat = true;
-        continue;
-      }
-
-      s = pathStr.substring(sidx, idx);
-      return isFloat ? parseFloat(s) : parseInt(s);
-    }
-
-    s = pathStr.substring(sidx);
-    return isFloat ? parseFloat(s) : parseInt(s);
-  }
-
-  function nextIsNum() {
-    var c;
-    // do permanently eat any delims...
-    while (idx < len) {
-      c = pathStr.charCodeAt(idx);
-      if (c !== COMMA && c !== SPACE)
-        break;
-      idx++;
-    }
-    c = pathStr.charCodeAt(idx);
-    return (c === MINUS || (DIGIT_0 <= c && c <= DIGIT_9));
-  }
-
-  var canRepeat;
-  activeCmd = pathStr[0];
-  while (idx <= len) {
-    canRepeat = true;
-    switch (activeCmd) {
-      // moveto commands, become lineto's if repeated
-      case 'M':
-        x = eatNum();
-        y = eatNum();
-        path.moveTo(x, y);
-        activeCmd = 'L';
-      firstX = x;
-      firstY = y;
-        break;
-      case 'm':
-        x += eatNum();
-        y += eatNum();
-        path.moveTo(x, y);
-        activeCmd = 'l';
-      firstX = x;
-      firstY = y;
-        break;
-      case 'Z':
-      case 'z':
-        canRepeat = false;
-        if (x !== firstX || y !== firstY)
-          path.lineTo(firstX, firstY);
-        break;
-      // - lines!
-      case 'L':
-      case 'H':
-      case 'V':
-        nx = (activeCmd === 'V') ? x : eatNum();
-        ny = (activeCmd === 'H') ? y : eatNum();
-        path.lineTo(nx, ny);
-        x = nx;
-        y = ny;
-        break;
-      case 'l':
-      case 'h':
-      case 'v':
-        nx = (activeCmd === 'v') ? x : (x + eatNum());
-        ny = (activeCmd === 'h') ? y : (y + eatNum());
-        path.lineTo(nx, ny);
-        x = nx;
-        y = ny;
-        break;
-      // - cubic bezier
-      case 'C':
-        x1 = eatNum(); y1 = eatNum();
-      case 'S':
-        if (activeCmd === 'S') {
-          x1 = 2 * x - x2; y1 = 2 * y - y2;
-        }
-        x2 = eatNum();
-        y2 = eatNum();
-        nx = eatNum();
-        ny = eatNum();
-        path.bezierCurveTo(x1, y1, x2, y2, nx, ny);
-        x = nx; y = ny;
-        break;
-      case 'c':
-        x1 = x + eatNum();
-        y1 = y + eatNum();
-      case 's':
-        if (activeCmd === 's') {
-          x1 = 2 * x - x2;
-          y1 = 2 * y - y2;
-        }
-        x2 = x + eatNum();
-        y2 = y + eatNum();
-        nx = x + eatNum();
-        ny = y + eatNum();
-        path.bezierCurveTo(x1, y1, x2, y2, nx, ny);
-        x = nx; y = ny;
-        break;
-      // - quadratic bezier
-      case 'Q':
-        x1 = eatNum(); y1 = eatNum();
-      case 'T':
-        if (activeCmd === 'T') {
-          x1 = 2 * x - x1;
-          y1 = 2 * y - y1;
-        }
-        nx = eatNum();
-        ny = eatNum();
-        path.quadraticCurveTo(x1, y1, nx, ny);
-        x = nx;
-        y = ny;
-        break;
-      case 'q':
-        x1 = x + eatNum();
-        y1 = y + eatNum();
-      case 't':
-        if (activeCmd === 't') {
-          x1 = 2 * x - x1;
-          y1 = 2 * y - y1;
-        }
-        nx = x + eatNum();
-        ny = y + eatNum();
-        path.quadraticCurveTo(x1, y1, nx, ny);
-        x = nx; y = ny;
-        break;
-      // - elliptical arc
-      case 'A':
-        rx = eatNum();
-        ry = eatNum();
-        xar = eatNum() * DEGS_TO_RADS;
-        laf = eatNum();
-        sf = eatNum();
-        nx = eatNum();
-        ny = eatNum();
-        if (rx !== ry) {
-          console.warn("Forcing elliptical arc to be a circular one :(",
-                       rx, ry);
-        }
-        // SVG implementation notes does all the math for us! woo!
-        // http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
-        // step1, using x1 as x1'
-        x1 = Math.cos(xar) * (x - nx) / 2 + Math.sin(xar) * (y - ny) / 2;
-        y1 = -Math.sin(xar) * (x - nx) / 2 + Math.cos(xar) * (y - ny) / 2;
-        // step 2, using x2 as cx'
-        var norm = Math.sqrt(
-                     (rx*rx * ry*ry - rx*rx * y1*y1 - ry*ry * x1*x1) /
-                     (rx*rx * y1*y1 + ry*ry * x1*x1));
-        if (laf === sf)
-          norm = -norm;
-        x2 = norm * rx * y1 / ry;
-        y2 = norm * -ry * x1 / rx;
-        // step 3
-        cx = Math.cos(xar) * x2 - Math.sin(xar) * y2 + (x + nx) / 2;
-        cy = Math.sin(xar) * x2 + Math.cos(xar) * y2 + (y + ny) / 2;
-
-        var u = new THREE.Vector2(1, 0),
-            v = new THREE.Vector2((x1 - x2) / rx,
-                                  (y1 - y2) / ry);
-        var startAng = Math.acos(u.dot(v) / u.length() / v.length());
-        if (u.x * v.y - u.y * v.x < 0)
-          startAng = -startAng;
-
-        // we can reuse 'v' from start angle as our 'u' for delta angle
-        u.x = (-x1 - x2) / rx;
-        u.y = (-y1 - y2) / ry;
-
-        var deltaAng = Math.acos(v.dot(u) / v.length() / u.length());
-        // This normalization ends up making our curves fail to triangulate...
-        if (v.x * u.y - v.y * u.x < 0)
-          deltaAng = -deltaAng;
-        if (!sf && deltaAng > 0)
-          deltaAng -= Math.PI * 2;
-        if (sf && deltaAng < 0)
-          deltaAng += Math.PI * 2;
-
-        path.absarc(cx, cy, rx, startAng, startAng + deltaAng, sf);
-        x = nx;
-        y = ny;
-        break;
-      default:
-        throw new Error("weird path command: " + activeCmd);
-    }
-    // just reissue the command
-    if (canRepeat && nextIsNum())
-      continue;
-    activeCmd = pathStr[idx++];
-  }
-
-  return path;
+	var path = new THREE.Shape();
+
+	var idx = 1, len = pathStr.length, activeCmd,
+		x = 0, y = 0, nx = 0, ny = 0, firstX = null, firstY = null,
+		x1 = 0, x2 = 0, y1 = 0, y2 = 0,
+		rx = 0, ry = 0, xar = 0, laf = 0, sf = 0, cx, cy;
+
+	function eatNum() {
+		var sidx, c, isFloat = false, s;
+		// eat delims
+		while (idx < len) {
+			c = pathStr.charCodeAt(idx);
+			if (c !== COMMA && c !== SPACE)
+				break;
+			idx++;
+		}
+		if (c === MINUS)
+			sidx = idx++;
+		else
+			sidx = idx;
+		// eat number
+		while (idx < len) {
+			c = pathStr.charCodeAt(idx);
+			if (DIGIT_0 <= c && c <= DIGIT_9) {
+				idx++;
+				continue;
+			}
+			else if (c === PERIOD) {
+				idx++;
+				isFloat = true;
+				continue;
+			}
+
+			s = pathStr.substring(sidx, idx);
+			return isFloat ? parseFloat(s) : parseInt(s);
+		}
+
+		s = pathStr.substring(sidx);
+		return isFloat ? parseFloat(s) : parseInt(s);
+	}
+
+	function nextIsNum() {
+		var c;
+		// do permanently eat any delims...
+		while (idx < len) {
+			c = pathStr.charCodeAt(idx);
+			if (c !== COMMA && c !== SPACE)
+				break;
+			idx++;
+		}
+		c = pathStr.charCodeAt(idx);
+		return (c === MINUS || (DIGIT_0 <= c && c <= DIGIT_9));
+	}
+
+	var canRepeat;
+	activeCmd = pathStr[0];
+	while (idx <= len) {
+		canRepeat = true;
+		switch (activeCmd) {
+			// moveto commands, become lineto's if repeated
+			case 'M':
+				x = eatNum();
+				y = eatNum();
+				path.moveTo(x, y);
+				activeCmd = 'L';
+				firstX = x;
+				firstY = y;
+				break;
+			case 'm':
+				x += eatNum();
+				y += eatNum();
+				path.moveTo(x, y);
+				activeCmd = 'l';
+				firstX = x;
+				firstY = y;
+				break;
+			case 'Z':
+			case 'z':
+				canRepeat = false;
+				if (x !== firstX || y !== firstY)
+					path.lineTo(firstX, firstY);
+				break;
+			// - lines!
+			case 'L':
+			case 'H':
+			case 'V':
+				nx = (activeCmd === 'V') ? x : eatNum();
+				ny = (activeCmd === 'H') ? y : eatNum();
+				path.lineTo(nx, ny);
+				x = nx;
+				y = ny;
+				break;
+			case 'l':
+			case 'h':
+			case 'v':
+				nx = (activeCmd === 'v') ? x : (x + eatNum());
+				ny = (activeCmd === 'h') ? y : (y + eatNum());
+				path.lineTo(nx, ny);
+				x = nx;
+				y = ny;
+				break;
+			// - cubic bezier
+			case 'C':
+				x1 = eatNum(); y1 = eatNum();
+			case 'S':
+				if (activeCmd === 'S') {
+					x1 = 2 * x - x2; y1 = 2 * y - y2;
+				}
+				x2 = eatNum();
+				y2 = eatNum();
+				nx = eatNum();
+				ny = eatNum();
+				path.bezierCurveTo(x1, y1, x2, y2, nx, ny);
+				x = nx; y = ny;
+				break;
+			case 'c':
+				x1 = x + eatNum();
+				y1 = y + eatNum();
+			case 's':
+				if (activeCmd === 's') {
+					x1 = 2 * x - x2;
+					y1 = 2 * y - y2;
+				}
+				x2 = x + eatNum();
+				y2 = y + eatNum();
+				nx = x + eatNum();
+				ny = y + eatNum();
+				path.bezierCurveTo(x1, y1, x2, y2, nx, ny);
+				x = nx; y = ny;
+				break;
+			// - quadratic bezier
+			case 'Q':
+				x1 = eatNum(); y1 = eatNum();
+			case 'T':
+				if (activeCmd === 'T') {
+					x1 = 2 * x - x1;
+					y1 = 2 * y - y1;
+				}
+				nx = eatNum();
+				ny = eatNum();
+				path.quadraticCurveTo(x1, y1, nx, ny);
+				x = nx;
+				y = ny;
+				break;
+			case 'q':
+				x1 = x + eatNum();
+				y1 = y + eatNum();
+			case 't':
+				if (activeCmd === 't') {
+					x1 = 2 * x - x1;
+					y1 = 2 * y - y1;
+				}
+				nx = x + eatNum();
+				ny = y + eatNum();
+				path.quadraticCurveTo(x1, y1, nx, ny);
+				x = nx; y = ny;
+				break;
+			// - elliptical arc
+			case 'A':
+				rx = eatNum();
+				ry = eatNum();
+				xar = eatNum() * DEGS_TO_RADS;
+				laf = eatNum();
+				sf = eatNum();
+				nx = eatNum();
+				ny = eatNum();
+				if (rx !== ry) {
+					console.warn("Forcing elliptical arc to be a circular one :(",
+						rx, ry);
+				}
+				// SVG implementation notes does all the math for us! woo!
+				// http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
+				// step1, using x1 as x1'
+				x1 = Math.cos(xar) * (x - nx) / 2 + Math.sin(xar) * (y - ny) / 2;
+				y1 = -Math.sin(xar) * (x - nx) / 2 + Math.cos(xar) * (y - ny) / 2;
+				// step 2, using x2 as cx'
+				var norm = Math.sqrt(
+					 (rx*rx * ry*ry - rx*rx * y1*y1 - ry*ry * x1*x1) /
+					 (rx*rx * y1*y1 + ry*ry * x1*x1));
+				if (laf === sf)
+					norm = -norm;
+				x2 = norm * rx * y1 / ry;
+				y2 = norm * -ry * x1 / rx;
+				// step 3
+				cx = Math.cos(xar) * x2 - Math.sin(xar) * y2 + (x + nx) / 2;
+				cy = Math.sin(xar) * x2 + Math.cos(xar) * y2 + (y + ny) / 2;
+
+				var u = new THREE.Vector2(1, 0),
+					v = new THREE.Vector2((x1 - x2) / rx,
+					                      (y1 - y2) / ry);
+				var startAng = Math.acos(u.dot(v) / u.length() / v.length());
+				if (u.x * v.y - u.y * v.x < 0)
+					startAng = -startAng;
+
+				// we can reuse 'v' from start angle as our 'u' for delta angle
+				u.x = (-x1 - x2) / rx;
+				u.y = (-y1 - y2) / ry;
+
+				var deltaAng = Math.acos(v.dot(u) / v.length() / u.length());
+				// This normalization ends up making our curves fail to triangulate...
+				if (v.x * u.y - v.y * u.x < 0)
+					deltaAng = -deltaAng;
+				if (!sf && deltaAng > 0)
+					deltaAng -= Math.PI * 2;
+				if (sf && deltaAng < 0)
+					deltaAng += Math.PI * 2;
+
+				path.absarc(cx, cy, rx, startAng, startAng + deltaAng, sf);
+				x = nx;
+				y = ny;
+				break;
+			default:
+				throw new Error("weird path command: " + activeCmd);
+		}
+		// just reissue the command
+		if (canRepeat && nextIsNum())
+			continue;
+		activeCmd = pathStr[idx++];
+	}
+
+	return path;
 }
 }
 }
 }
 
 
@@ -275,253 +275,261 @@ d3threeD($d3g);
 
 
 
 
 <script>
 <script>
+/// Part from g0v/twgeojson
 /// Graphic Engine and Geo Data Init Functions
 /// Graphic Engine and Geo Data Init Functions
 
 
 var addGeoObject = function( group, svgObject ) {
 var addGeoObject = function( group, svgObject ) {
-    var i,j, len, len1;
-    var path, mesh, color, material, amount, simpleShapes, simpleShape, shape3d, x, toAdd, results = [];
-    var thePaths = svgObject.paths;
-    var theAmounts = svgObject.amounts;
-    var theColors = svgObject.colors;
-    var theCenter = svgObject.center;
-
-    len = thePaths.length;
-    for (i = 0; i < len; ++i) {
-        path = $d3g.transformSVGPath( thePaths[i] );
-        color = new THREE.Color( theColors[i] ); 
-        material = new THREE.MeshLambertMaterial({
-            color: color,
-            ambient: color,
-            emissive: color,
-        });
-        amount = theAmounts[i];
-        simpleShapes = path.toShapes(true);
-        len1 = simpleShapes.length;
-        for (j = 0; j < len1; ++j) {
-            simpleShape = simpleShapes[j];
-            shape3d = simpleShape.extrude({
-                amount: amount,
-                bevelEnabled: false
-            });
-            mesh = new THREE.Mesh(shape3d, material);
-            mesh.rotation.x = Math.PI;
-            mesh.translateZ( - amount - 1);
-            mesh.translateX( - theCenter.x);
-            mesh.translateY( - theCenter.y);
-            group.add(mesh);
-        }
-    }
+	var i,j, len, len1;
+	var path, mesh, color, material, amount, simpleShapes, simpleShape, shape3d, x, toAdd, results = [];
+	var thePaths = svgObject.paths;
+	var theAmounts = svgObject.amounts;
+	var theColors = svgObject.colors;
+	var theCenter = svgObject.center;
+
+	len = thePaths.length;
+	for (i = 0; i < len; ++i) {
+		path = $d3g.transformSVGPath( thePaths[i] );
+		color = new THREE.Color( theColors[i] ); 
+		material = new THREE.MeshLambertMaterial({
+			color: color,
+			ambient: color,
+			emissive: color,
+		});
+		amount = theAmounts[i];
+		simpleShapes = path.toShapes(true);
+		len1 = simpleShapes.length;
+		for (j = 0; j < len1; ++j) {
+			simpleShape = simpleShapes[j];
+			shape3d = simpleShape.extrude({
+				amount: amount,
+				bevelEnabled: false
+			});
+			mesh = new THREE.Mesh(shape3d, material);
+			mesh.rotation.x = Math.PI;
+			mesh.translateZ( - amount - 1);
+			mesh.translateX( - theCenter.x);
+			mesh.translateY( - theCenter.y);
+			group.add(mesh);
+		}
+	}
 };
 };
 
 
 var init3d = function(){
 var init3d = function(){
-    var near = 1.0;
-    var far = 10000.0;
-
-    /// Global : renderer
-    renderer = new THREE.WebGLRenderer( { antialias: true } );
-    renderer.setClearColor( 0xb0b0b0 );
-    renderer.setSize( window.innerWidth, window.innerHeight );
-
-    /// Global : scene
-    scene = new THREE.Scene();
-
-    /// Global : camera
-    camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, near, far );
-    camera.position.set( 0, 0, 200 );
-
-    /// Global : group
-    group = new THREE.Object3D();
-    group.position.x = 0.0;
-    group.position.y = 0.0;
-    group.position.z = 0.0;
-    scene.add( group );
-
-    /// direct light
-    var light = new THREE.DirectionalLight( 0x404040 );
-    light.position.set( 0.75, 0.75, 1.0 ).normalize();
-    scene.add( light );
-
-    /// ambient light
-    var ambientLight = new THREE.AmbientLight(0x404040);
-    scene.add( ambientLight );
-
-    /// backgroup grids
-    var plane = new THREE.Mesh(
-            new THREE.PlaneGeometry(160, 160, 20, 20), 
-            new THREE.MeshBasicMaterial({ color: 0x7f7f7f, wireframe: true }));
-    plane.rotation.x = Math.PI;
-    group.add( plane );
-
-    var obj = initSVGObject();
-    addGeoObject( group, obj );
+	var near = 1.0;
+	var far = 10000.0;
+
+	/// Global : renderer
+	renderer = new THREE.WebGLRenderer( { antialias: true } );
+	renderer.setClearColor( 0xb0b0b0 );
+	renderer.setSize( window.innerWidth, window.innerHeight );
+
+	/// Global : scene
+	scene = new THREE.Scene();
+
+	/// Global : camera
+	camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, near, far );
+	camera.position.set( 0, 0, 200 );
+
+	/// Global : group
+	group = new THREE.Object3D();
+	group.position.x = 0.0;
+	group.position.y = 0.0;
+	group.position.z = 0.0;
+	scene.add( group );
+
+	/// direct light
+	var light = new THREE.DirectionalLight( 0x404040 );
+	light.position.set( 0.75, 0.75, 1.0 ).normalize();
+	scene.add( light );
+
+	/// ambient light
+	var ambientLight = new THREE.AmbientLight(0x404040);
+	scene.add( ambientLight );
+
+	/// backgroup grids
+	var plane = new THREE.Mesh(
+			new THREE.PlaneGeometry(160, 160, 20, 20), 
+			new THREE.MeshBasicMaterial({ color: 0x7f7f7f, wireframe: true }));
+	plane.rotation.x = Math.PI;
+	group.add( plane );
+
+	var obj = initSVGObject();
+	addGeoObject( group, obj );
 };
 };
 
 
 var initSVGObject = function() {
 var initSVGObject = function() {
-    var obj = {};
-
-    /// The geo data from Taipei City, Keelung City, Taipei County in SVG form
-    obj.paths = [
-        /// Taipei City
-        "M366.2182,108.9780 L368.0329,110.3682 L367.5922,112.4411 L369.9258,116.0311 L368.9827,117.3543 " +
-        "L371.5686,119.8491 L370.5599,121.7206 L372.9314,124.8009 L368.8889,126.7603 L369.2695,130.7622 " +
-        "L366.1499,130.3388 L363.4698,128.1161 L362.9256,125.6018 L360.8153,126.4025 L360.2968,124.3588 " +
-        "L361.9519,121.1623 L360.4475,118.7162 L358.1163,117.8678 L358.7094,115.7577 L361.6243,112.4576 Z",
-        /// Keelung City
-        "M380.2689,113.3850 L383.5604,114.2370 L383.7404,114.2386 L385.4082,115.6247 L384.9725,117.4631 " +
-        "L381.6681,117.9439 L383.0209,121.0914 L379.4649,122.7061 L373.4987,118.8487 L372.0980,114.7589 " +
-        "L377.9716,112.0707 Z",
-        /// Taipei County
-        "M359.4486,155.6690 L357.0422,152.7420 L355.1688,148.0173 L357.1186,145.8045 L354.1323,141.2242 " +
-        "L351.1807,141.6609 L348.9387,140.5372 L349.5415,137.8396 L347.5174,136.1694 L347.6299,129.2327 " +
-        "L351.4192,128.8067 L354.2518,125.3113 L352.5805,121.8038 L349.3190,120.9429 L344.3277,116.7676 " +
-        "L350.9772,115.1221 L354.5759,112.5371 L354.5667,110.6949 L357.4098,105.7489 L362.3963,101.8443 " +
-        "L364.4415,101.0819 L364.5314,101.0828 L364.6209,101.1230 L364.7698,101.2029 L368.1221,101.5115 " +
-        "L371.7216,104.1338 L372.2958,106.7261 L375.5949,109.6971 L377.0415,108.8875 L377.0737,108.6526 " +
-        "L377.4037,108.6165 L376.8840,109.7091 L376.7323,109.9037 L377.9416,112.0705 L371.7970,114.8736 " + 
-        "L374.0935,119.4031 L380.7848,122.7963 L382.6529,121.9897 L381.5792,117.8256 L385.0339,117.3069 " +
-        "L385.4082,115.6247 L388.7014,116.3969 L389.8697,116.6024 L390.0206,116.4860 L391.0396,116.6118 " +
-        "L394.6665,116.9929 L394.4694,119.2255 L394.3172,119.4987 L395.3792,121.8977 L395.2728,124.0526 " +
-        "L397.2123,125.6350 L401.1709,126.2516 L401.2612,126.2130 L401.4086,126.6060 L400.1992,127.7733 " +
-        "L399.7769,128.0446 L399.6247,128.3179 L398.1779,129.0521 L394.2418,129.2969 L388.7324,130.9385 " +
-        "L389.2782,134.0003 L383.7237,137.0111 L381.7445,139.9336 L379.7001,139.9546 L376.1539,143.0580 " +
-        "L371.3022,144.1094 L368.6009,146.5914 L368.7361,151.1399 L363.6153,154.4980 " +
-        /// Taipei County hole.
-        "M363.4600,128.3904 L366.6300,130.3829 L369.3732,129.3913 L369.5603,125.6695 L374.3989,125.1677 " +
-        "L370.8412,123.6440 L371.0684,118.8252 L369.0431,117.3157 L369.6882,115.7936 L367.8578,112.8749 " +
-        "L368.1217,110.4867 L366.5152,109.2554 L361.9554,112.3435 L358.1163,117.8678 L361.7218,120.2192 " +
-        "L360.7261,126.3232 L362.8064,125.5221 Z"];
-
-    obj.amounts = [ 19, 20, 21 ];
-    obj.colors =  [ 0xC07000, 0xC08000, 0xC0A000 ];
-    obj.center = { x:365, y:125 };
-
-    return obj;
+	var obj = {};
+
+	/// The geo data from Taipei City, Keelung City, Taipei County in SVG form
+	obj.paths = [
+		/// Taipei City
+		"M366.2182,108.9780 L368.0329,110.3682 L367.5922,112.4411 L369.9258,116.0311 L368.9827,117.3543 " +
+		"L371.5686,119.8491 L370.5599,121.7206 L372.9314,124.8009 L368.8889,126.7603 L369.2695,130.7622 " +
+		"L366.1499,130.3388 L363.4698,128.1161 L362.9256,125.6018 L360.8153,126.4025 L360.2968,124.3588 " +
+		"L361.9519,121.1623 L360.4475,118.7162 L358.1163,117.8678 L358.7094,115.7577 L361.6243,112.4576 Z",
+		/// Keelung City
+		"M380.2689,113.3850 L383.5604,114.2370 L383.7404,114.2386 L385.4082,115.6247 L384.9725,117.4631 " +
+		"L381.6681,117.9439 L383.0209,121.0914 L379.4649,122.7061 L373.4987,118.8487 L372.0980,114.7589 " +
+		"L377.9716,112.0707 Z",
+		/// Taipei County
+		"M359.4486,155.6690 L357.0422,152.7420 L355.1688,148.0173 L357.1186,145.8045 L354.1323,141.2242 " +
+		"L351.1807,141.6609 L348.9387,140.5372 L349.5415,137.8396 L347.5174,136.1694 L347.6299,129.2327 " +
+		"L351.4192,128.8067 L354.2518,125.3113 L352.5805,121.8038 L349.3190,120.9429 L344.3277,116.7676 " +
+		"L350.9772,115.1221 L354.5759,112.5371 L354.5667,110.6949 L357.4098,105.7489 L362.3963,101.8443 " +
+		"L364.4415,101.0819 L364.5314,101.0828 L364.6209,101.1230 L364.7698,101.2029 L368.1221,101.5115 " +
+		"L371.7216,104.1338 L372.2958,106.7261 L375.5949,109.6971 L377.0415,108.8875 L377.0737,108.6526 " +
+		"L377.4037,108.6165 L376.8840,109.7091 L376.7323,109.9037 L377.9416,112.0705 L371.7970,114.8736 " + 
+		"L374.0935,119.4031 L380.7848,122.7963 L382.6529,121.9897 L381.5792,117.8256 L385.0339,117.3069 " +
+		"L385.4082,115.6247 L388.7014,116.3969 L389.8697,116.6024 L390.0206,116.4860 L391.0396,116.6118 " +
+		"L394.6665,116.9929 L394.4694,119.2255 L394.3172,119.4987 L395.3792,121.8977 L395.2728,124.0526 " +
+		"L397.2123,125.6350 L401.1709,126.2516 L401.2612,126.2130 L401.4086,126.6060 L400.1992,127.7733 " +
+		"L399.7769,128.0446 L399.6247,128.3179 L398.1779,129.0521 L394.2418,129.2969 L388.7324,130.9385 " +
+		"L389.2782,134.0003 L383.7237,137.0111 L381.7445,139.9336 L379.7001,139.9546 L376.1539,143.0580 " +
+		"L371.3022,144.1094 L368.6009,146.5914 L368.7361,151.1399 L363.6153,154.4980 " +
+		/// Taipei County hole.
+		"M363.4600,128.3904 L366.6300,130.3829 L369.3732,129.3913 L369.5603,125.6695 L374.3989,125.1677 " +
+		"L370.8412,123.6440 L371.0684,118.8252 L369.0431,117.3157 L369.6882,115.7936 L367.8578,112.8749 " +
+		"L368.1217,110.4867 L366.5152,109.2554 L361.9554,112.3435 L358.1163,117.8678 L361.7218,120.2192 " +
+		"L360.7261,126.3232 L362.8064,125.5221 Z"];
+
+	obj.amounts = [ 19, 20, 21 ];
+	obj.colors =  [ 0xC07000, 0xC08000, 0xC0A000 ];
+	obj.center = { x:365, y:125 };
+
+	return obj;
 };
 };
 </script>
 </script>
 
 
 
 
 
 
 <script>
 <script>
-    /// Events from extrude shapes example
+	/// Events from extrude shapes example
 
 
-    function onWindowResize() {
+	function onWindowResize() {
 
 
-        windowHalfX = window.innerWidth / 2;
-        windowHalfY = window.innerHeight / 2;
+		windowHalfX = window.innerWidth / 2;
+		windowHalfY = window.innerHeight / 2;
 
 
-        camera.aspect = window.innerWidth / window.innerHeight;
-        camera.updateProjectionMatrix();
+		camera.aspect = window.innerWidth / window.innerHeight;
+		camera.updateProjectionMatrix();
 
 
-        renderer.setSize( window.innerWidth, window.innerHeight );
-    };
+		renderer.setSize( window.innerWidth, window.innerHeight );
+	};
 
 
-    function onDocumentMouseDown( event ) {
+	function onDocumentMouseDown( event ) {
 
 
-        event.preventDefault();
+		event.preventDefault();
 
 
-        document.addEventListener( 'mousemove', onDocumentMouseMove, false );
-        document.addEventListener( 'mouseup', onDocumentMouseUp, false );
-        document.addEventListener( 'mouseout', onDocumentMouseOut, false );
+		document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+		document.addEventListener( 'mouseup', onDocumentMouseUp, false );
+		document.addEventListener( 'mouseout', onDocumentMouseOut, false );
 
 
-        mouseXOnMouseDown = event.clientX - windowHalfX;
-        targetRotationOnMouseDown = targetRotation;
-    };
+		mouseXOnMouseDown = event.clientX - windowHalfX;
+		targetRotationOnMouseDown = targetRotation;
+	};
 
 
-    function onDocumentMouseMove( event ) {
+	function onDocumentMouseMove( event ) {
 
 
-        mouseX = event.clientX - windowHalfX;
+		mouseX = event.clientX - windowHalfX;
 
 
-        targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
-    };
+		targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
+	};
 
 
-    function onDocumentMouseUp( event ) {
+	function onDocumentMouseUp( event ) {
 
 
-        document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
-        document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
-        document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
-    };
+		document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
+		document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
+		document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
+	};
 
 
-    function onDocumentMouseOut( event ) {
+	function onDocumentMouseOut( event ) {
 
 
-        document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
-        document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
-        document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
-    };
+		document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
+		document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
+		document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
+	};
 
 
-    function onDocumentTouchStart( event ) {
+	function onDocumentTouchStart( event ) {
 
 
-        if ( event.touches.length == 1 ) {
+		if ( event.touches.length == 1 ) {
 
 
-            event.preventDefault();
+			event.preventDefault();
 
 
-            mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
-            targetRotationOnMouseDown = targetRotation;
-        }
-    };
+			mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
+			targetRotationOnMouseDown = targetRotation;
+		}
+	};
 
 
-    function onDocumentTouchMove( event ) {
+	function onDocumentTouchMove( event ) {
 
 
-        if ( event.touches.length == 1 ) {
+		if ( event.touches.length == 1 ) {
 
 
-            event.preventDefault();
+			event.preventDefault();
 
 
-            mouseX = event.touches[ 0 ].pageX - windowHalfX;
-            targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
-        }
-    };
+			mouseX = event.touches[ 0 ].pageX - windowHalfX;
+			targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
+		}
+	};
 
 
-    function animate() {
+	function animate() {
 
 
-        /// compatibility : http://caniuse.com/requestanimationframe
-        requestAnimationFrame( animate );
+		/// compatibility : http://caniuse.com/requestanimationframe
+		requestAnimationFrame( animate );
 
 
-        render();
-    };
+		render();
+		stats.update();
+	};
 
 
-    function render() {
+	function render() {
 
 
-        group.rotation.y += ( targetRotation - group.rotation.y ) * 0.05;
-        renderer.render( scene, camera );
-    };
+		group.rotation.y += ( targetRotation - group.rotation.y ) * 0.05;
+		renderer.render( scene, camera );
+	};
 </script>
 </script>
 
 
 
 
 
 
 <script>
 <script>
-    /// Main
+	/// Main
 
 
-    var renderer;
-    var scene, camera, group;
+	var renderer, stats;
+	var scene, camera, group;
 
 
-    var targetRotation = 0;
-    var targetRotationOnMouseDown = 0;
+	var targetRotation = 0;
+	var targetRotationOnMouseDown = 0;
 
 
-    var mouseX = 0;
-    var mouseXOnMouseDown = 0;
+	var mouseX = 0;
+	var mouseXOnMouseDown = 0;
 
 
-    var windowHalfX = window.innerWidth / 2;
-    var windowHalfY = window.innerHeight / 2;
+	var windowHalfX = window.innerWidth / 2;
+	var windowHalfY = window.innerHeight / 2;
 
 
-    var container = document.createElement( 'div' );
-    document.body.appendChild( container );
+	var container = document.createElement( 'div' );
+	document.body.appendChild( container );
 
 
-    var info = document.createElement( 'div' );
-    info.style.position = 'absolute';
-    info.style.top = '10px';
-    info.style.width = '100%';
-    info.style.textAlign = 'center';
-    info.innerHTML = 'Shapes Extrusion via Geo Data<br/>Drag to spin';
-    container.appendChild( info );
+	var info = document.createElement( 'div' );
+	info.style.position = 'absolute';
+	info.style.top = '10px';
+	info.style.width = '100%';
+	info.style.textAlign = 'center';
+	info.innerHTML = 'Shapes Extrusion via Geo Data<br/>Drag to spin';
+	container.appendChild( info );
 
 
-    init3d();
+	init3d();
 
 
 	container.appendChild( renderer.domElement );
 	container.appendChild( renderer.domElement );
-    document.addEventListener( 'mousedown', onDocumentMouseDown, false );
-    document.addEventListener( 'touchstart', onDocumentTouchStart, false );
-    document.addEventListener( 'touchmove', onDocumentTouchMove, false );
-    window.addEventListener( 'resize', onWindowResize, false );
 
 
-    animate();
+	stats = new Stats();
+	stats.domElement.style.position = 'absolute';
+	stats.domElement.style.top = '0px';
+	container.appendChild( stats.domElement );
+
+	document.addEventListener( 'mousedown', onDocumentMouseDown, false );
+	document.addEventListener( 'touchstart', onDocumentTouchStart, false );
+	document.addEventListener( 'touchmove', onDocumentTouchMove, false );
+	window.addEventListener( 'resize', onWindowResize, false );
+
+	animate();
 </script>
 </script>
 
 
 
 

+ 7 - 5
examples/webgl_geometry_extrude_uvs2.html

@@ -2,7 +2,7 @@
 <html lang="en" id="html-el">
 <html lang="en" id="html-el">
 	<head>
 	<head>
 		<title>three.js webgl - UV mapped ExtrudeGeometry</title>
 		<title>three.js webgl - UV mapped ExtrudeGeometry</title>
-		
+
 		<script type="text/javascript" src="../build/three.min.js"></script>
 		<script type="text/javascript" src="../build/three.min.js"></script>
 		<script type="text/javascript" src="js/UVsUtils.js"></script>
 		<script type="text/javascript" src="js/UVsUtils.js"></script>
 
 
@@ -26,7 +26,7 @@
 
 
 	window.launch = function() {
 	window.launch = function() {
 
 
-		camera = new THREE.PerspectiveCamera(30, WIDTH / HEIGHT);
+		camera = new THREE.PerspectiveCamera(30, WIDTH / HEIGHT, 1, 10000);
 		camera.position.z = 20;
 		camera.position.z = 20;
 
 
 		scene = new THREE.Scene();
 		scene = new THREE.Scene();
@@ -45,8 +45,10 @@
 
 
 		// show canvas
 		// show canvas
 		targetCanvas = renderer.domElement;
 		targetCanvas = renderer.domElement;
-		targetCanvas.width  = WIDTH;
-		targetCanvas.height = HEIGHT;
+
+		/// Don't add it
+		//targetCanvas.width  = WIDTH;
+		//targetCanvas.height = HEIGHT;
 		document.getElementById('canvas-container').appendChild(targetCanvas);
 		document.getElementById('canvas-container').appendChild(targetCanvas);
 
 
 		setupAnimation();
 		setupAnimation();
@@ -177,7 +179,7 @@
 		</script>
 		</script>
 	</head>
 	</head>
 	
 	
-	<body onload="void launch()">
+	<body onload="launch()">
 		<div>
 		<div>
 			<form id="repeat-setting">
 			<form id="repeat-setting">
 				U repeat: &nbsp;
 				U repeat: &nbsp;

+ 5 - 0
utils/exporters/blender/README.md

@@ -29,6 +29,11 @@ By default, this should look like:
 
 
     /home/USERNAME/.config/blender/2.6X/scripts/addons
     /home/USERNAME/.config/blender/2.6X/scripts/addons
 
 
+For Ubuntu users who installed Blender 2.6.8 via apt-get, this is the location:
+
+    /usr/lib/blender/scripts/addons
+    
+
 ## Usage
 ## Usage
 
 
 Activate the Import-Export addon under "User Preferences" > "Addons" and then use the regular Import and Export menu within Blender, select `Three.js (js)`.
 Activate the Import-Export addon under "User Preferences" > "Addons" and then use the regular Import and Export menu within Blender, select `Three.js (js)`.