Mr.doob 11 years ago
parent
commit
4c7be808f3
62 changed files with 3912 additions and 680 deletions
  1. 293 125
      build/three.js
  2. 37 35
      build/three.min.js
  3. 5 5
      docs/api/materials/Material.html
  4. 21 6
      docs/api/materials/ShaderMaterial.html
  5. 5 3
      docs/api/math/Box2.html
  6. 68 65
      docs/api/math/Box3.html
  7. 2 2
      docs/api/math/Frustum.html
  8. 50 56
      docs/api/math/Line3.html
  9. 72 76
      docs/api/math/Plane.html
  10. 48 57
      docs/api/math/Sphere.html
  11. 51 50
      docs/api/math/Triangle.html
  12. 3 3
      docs/api/math/Vector3.html
  13. 6 1
      docs/api/math/Vector4.html
  14. 1 3
      docs/api/renderers/WebGLRenderer.html
  15. 4 8
      docs/api/renderers/shaders/ShaderChunk.html
  16. 27 0
      docs/api/renderers/shaders/ShaderLib.html
  17. 28 0
      docs/api/renderers/shaders/UniformsLib.html
  18. 26 0
      docs/api/renderers/shaders/UniformsUtils.html
  19. 9 2
      docs/list.js
  20. 4 3
      editor/index.html
  21. 2 2
      examples/canvas_interactive_cubes.html
  22. 2 2
      examples/canvas_interactive_lines.html
  23. 4 4
      examples/canvas_interactive_particles.html
  24. 1 4
      examples/canvas_lights_pointlights.html
  25. 1 4
      examples/canvas_lights_pointlights_smooth.html
  26. 2 2
      examples/canvas_lines.html
  27. 2 2
      examples/canvas_materials.html
  28. 2 1
      examples/canvas_materials_video.html
  29. 5 2
      examples/css3d_periodictable.html
  30. 5 1
      examples/index.html
  31. 2 2
      examples/js/AudioObject.js
  32. 2 2
      examples/js/Mirror.js
  33. 1 1
      examples/js/Octree.js
  34. 236 0
      examples/js/SimulatorRenderer.js
  35. 594 0
      examples/js/TypedArrayUtils.js
  36. 95 71
      examples/js/controls/TrackballControls.js
  37. 3 3
      examples/js/controls/TransformControls.js
  38. 39 0
      examples/js/crossfade/gui.js
  39. 108 0
      examples/js/crossfade/scenes.js
  40. 165 0
      examples/js/crossfade/transition.js
  41. 2 0
      examples/js/loaders/ColladaLoader.js
  42. 1 1
      examples/js/loaders/ctm/ctm.js
  43. 96 0
      examples/js/postprocessing/BokehPass.js
  44. 1 1
      examples/js/renderers/CSS2DRenderer.js
  45. 2 2
      examples/js/renderers/SVGRenderer.js
  46. 9 9
      examples/js/renderers/WebGLDeferredRenderer.js
  47. 1 1
      examples/js/renderers/WebGLRenderer3.js
  48. BIN
      examples/textures/transition/transition1.png
  49. BIN
      examples/textures/transition/transition2.png
  50. BIN
      examples/textures/transition/transition3.png
  51. BIN
      examples/textures/transition/transition4.png
  52. BIN
      examples/textures/transition/transition5.png
  53. BIN
      examples/textures/transition/transition6.png
  54. 538 0
      examples/webgl_geometry_extrude_shapes2.html
  55. 7 5
      examples/webgl_geometry_extrude_uvs2.html
  56. 806 0
      examples/webgl_gpgpu_birds.html
  57. 4 1
      examples/webgl_loader_collada_skinning.html
  58. 247 0
      examples/webgl_nearestneighbour.html
  59. 99 0
      examples/webgl_postprocessing_crossfade.html
  60. 42 44
      examples/webgl_postprocessing_dof.html
  61. 25 12
      examples/webgl_sprites.html
  62. 1 1
      index.html

+ 293 - 125
build/three.js

@@ -4,7 +4,7 @@
  * @author bhouston / http://exocortex.com
  * @author bhouston / http://exocortex.com
  */
  */
 
 
-var THREE = { REVISION: '63' };
+var THREE = { REVISION: '64' };
 
 
 self.console = self.console || {
 self.console = self.console || {
 
 
@@ -469,54 +469,50 @@ THREE.Color.prototype = {
 
 
 	},
 	},
 
 
-	getHSL: function () {
+	getHSL: function ( optionalTarget ) {
 
 
-		var hsl = { h: 0, s: 0, l: 0 };
-
-		return function () {
-
-			// h,s,l ranges are in 0.0 - 1.0
-
-			var r = this.r, g = this.g, b = this.b;
+		// h,s,l ranges are in 0.0 - 1.0
 
 
-			var max = Math.max( r, g, b );
-			var min = Math.min( r, g, b );
+		var hsl = optionalTarget || { h: 0, s: 0, l: 0 };
 
 
-			var hue, saturation;
-			var lightness = ( min + max ) / 2.0;
+		var r = this.r, g = this.g, b = this.b;
 
 
-			if ( min === max ) {
+		var max = Math.max( r, g, b );
+		var min = Math.min( r, g, b );
 
 
-				hue = 0;
-				saturation = 0;
+		var hue, saturation;
+		var lightness = ( min + max ) / 2.0;
 
 
-			} else {
+		if ( min === max ) {
 
 
-				var delta = max - min;
+			hue = 0;
+			saturation = 0;
 
 
-				saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
+		} else {
 
 
-				switch ( max ) {
+			var delta = max - min;
 
 
-					case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
-					case g: hue = ( b - r ) / delta + 2; break;
-					case b: hue = ( r - g ) / delta + 4; break;
+			saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );
 
 
-				}
+			switch ( max ) {
 
 
-				hue /= 6;
+				case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;
+				case g: hue = ( b - r ) / delta + 2; break;
+				case b: hue = ( r - g ) / delta + 4; break;
 
 
 			}
 			}
 
 
-			hsl.h = hue;
-			hsl.s = saturation;
-			hsl.l = lightness;
+			hue /= 6;
 
 
-			return hsl;
+		}
 
 
-		};
+		hsl.h = hue;
+		hsl.s = saturation;
+		hsl.l = lightness;
 
 
-	}(),
+		return hsl;
+
+	},
 
 
 	getStyle: function () {
 	getStyle: function () {
 
 
@@ -1965,19 +1961,42 @@ THREE.Vector3.prototype = {
 
 
 	getPositionFromMatrix: function ( m ) {
 	getPositionFromMatrix: function ( m ) {
 
 
-		this.x = m.elements[12];
-		this.y = m.elements[13];
-		this.z = m.elements[14];
+		console.warn( "DEPRECATED: Vector3\'s .getPositionFromMatrix() has been renamed to .setFromMatrixPosition(). Please update your code." );
 
 
-		return this;
+		return this.setFromMatrixPosition( m );
 
 
 	},
 	},
 
 
 	getScaleFromMatrix: function ( m ) {
 	getScaleFromMatrix: function ( m ) {
 
 
-		var sx = this.set( m.elements[0], m.elements[1], m.elements[2] ).length();
-		var sy = this.set( m.elements[4], m.elements[5], m.elements[6] ).length();
-		var sz = this.set( m.elements[8], m.elements[9], m.elements[10] ).length();
+		console.warn( "DEPRECATED: Vector3\'s .getScaleFromMatrix() has been renamed to .setFromMatrixScale(). Please update your code." );
+
+		return this.setFromMatrixScale( m );
+	},
+
+	getColumnFromMatrix: function ( index, matrix ) {
+
+		console.warn( "DEPRECATED: Vector3\'s .getColumnFromMatrix() has been renamed to .setFromMatrixColumn(). Please update your code." );
+
+		return this.setFromMatrixColumn( index, matrix );
+
+	},
+
+	setFromMatrixPosition: function ( m ) {
+
+		this.x = m.elements[ 12 ];
+		this.y = m.elements[ 13 ];
+		this.z = m.elements[ 14 ];
+
+		return this;
+
+	},
+
+	setFromMatrixScale: function ( m ) {
+
+		var sx = this.set( m.elements[ 0 ], m.elements[ 1 ], m.elements[  2 ] ).length();
+		var sy = this.set( m.elements[ 4 ], m.elements[ 5 ], m.elements[  6 ] ).length();
+		var sz = this.set( m.elements[ 8 ], m.elements[ 9 ], m.elements[ 10 ] ).length();
 
 
 		this.x = sx;
 		this.x = sx;
 		this.y = sy;
 		this.y = sy;
@@ -1986,7 +2005,7 @@ THREE.Vector3.prototype = {
 		return this;
 		return this;
 	},
 	},
 
 
-	getColumnFromMatrix: function ( index, matrix ) {
+	setFromMatrixColumn: function ( index, matrix ) {
 
 
 		var offset = index * 4;
 		var offset = index * 4;
 
 
@@ -3353,12 +3372,14 @@ THREE.Box2.prototype = {
 
 
 	},
 	},
 
 
-	getParameter: function ( point ) {
+	getParameter: function ( point, optionalTarget ) {
 
 
 		// This can potentially have a divide by zero if the box
 		// This can potentially have a divide by zero if the box
 		// has a size dimension of 0.
 		// has a size dimension of 0.
 
 
-		return new THREE.Vector2(
+		var result = optionalTarget || new THREE.Vector2();
+
+		return result.set(
 			( point.x - this.min.x ) / ( this.max.x - this.min.x ),
 			( point.x - this.min.x ) / ( this.max.x - this.min.x ),
 			( point.y - this.min.y ) / ( this.max.y - this.min.y )
 			( point.y - this.min.y ) / ( this.max.y - this.min.y )
 		);
 		);
@@ -3678,12 +3699,14 @@ THREE.Box3.prototype = {
 
 
 	},
 	},
 
 
-	getParameter: function ( point ) {
+	getParameter: function ( point, optionalTarget ) {
 
 
 		// This can potentially have a divide by zero if the box
 		// This can potentially have a divide by zero if the box
 		// has a size dimension of 0.
 		// has a size dimension of 0.
 
 
-		return new THREE.Vector3(
+		var result = optionalTarget || new THREE.Vector3();
+
+		return result.set(
 			( point.x - this.min.x ) / ( this.max.x - this.min.x ),
 			( point.x - this.min.x ) / ( this.max.x - this.min.x ),
 			( point.y - this.min.y ) / ( this.max.y - this.min.y ),
 			( point.y - this.min.y ) / ( this.max.y - this.min.y ),
 			( point.z - this.min.z ) / ( this.max.z - this.min.z )
 			( point.z - this.min.z ) / ( this.max.z - this.min.z )
@@ -4627,7 +4650,7 @@ THREE.Matrix4.prototype = {
 
 
 		return function () {
 		return function () {
 
 
-			console.warn( 'DEPRECATED: Matrix4\'s .getPosition() has been removed. Use Vector3.getPositionFromMatrix( matrix ) instead.' );
+			console.warn( 'DEPRECATED: Matrix4\'s .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' );
 
 
 			var te = this.elements;
 			var te = this.elements;
 			return v1.set( te[12], te[13], te[14] );
 			return v1.set( te[12], te[13], te[14] );
@@ -5997,14 +6020,15 @@ THREE.Plane.prototype = {
 
 
 		var v1 = new THREE.Vector3();
 		var v1 = new THREE.Vector3();
 		var v2 = new THREE.Vector3();
 		var v2 = new THREE.Vector3();
+		var m1 = new THREE.Matrix3();
 
 
 		return function ( matrix, optionalNormalMatrix ) {
 		return function ( matrix, optionalNormalMatrix ) {
 
 
 			// compute new normal based on theory here:
 			// compute new normal based on theory here:
 			// http://www.songho.ca/opengl/gl_normaltransform.html
 			// http://www.songho.ca/opengl/gl_normaltransform.html
-			optionalNormalMatrix = optionalNormalMatrix || new THREE.Matrix3().getNormalMatrix( matrix );
-			var newNormal = v1.copy( this.normal ).applyMatrix3( optionalNormalMatrix );
-
+			var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix );
+			var newNormal = v1.copy( this.normal ).applyMatrix3( normalMatrix );
+			
 			var newCoplanarPoint = this.coplanarPoint( v2 );
 			var newCoplanarPoint = this.coplanarPoint( v2 );
 			newCoplanarPoint.applyMatrix4( matrix );
 			newCoplanarPoint.applyMatrix4( matrix );
 
 
@@ -6719,11 +6743,17 @@ THREE.EventDispatcher.prototype = {
 		if ( this._listeners === undefined ) return;
 		if ( this._listeners === undefined ) return;
 
 
 		var listeners = this._listeners;
 		var listeners = this._listeners;
-		var index = listeners[ type ].indexOf( listener );
+		var listenerArray = listeners[ type ];
 
 
-		if ( index !== - 1 ) {
+		if ( listenerArray !== undefined ) {
+
+			var index = listenerArray.indexOf( listener );
 
 
-			listeners[ type ].splice( index, 1 );
+			if ( index !== - 1 ) {
+
+				listenerArray.splice( index, 1 );
+
+			}
 
 
 		}
 		}
 
 
@@ -6806,7 +6836,7 @@ THREE.EventDispatcher.prototype = {
 
 
 		if ( object instanceof THREE.Sprite ) {
 		if ( object instanceof THREE.Sprite ) {
 
 
-			matrixPosition.getPositionFromMatrix( object.matrixWorld );
+			matrixPosition.setFromMatrixPosition( object.matrixWorld );
 			var distance = raycaster.ray.distanceToPoint( matrixPosition );
 			var distance = raycaster.ray.distanceToPoint( matrixPosition );
 
 
 			if ( distance > object.scale.x ) {
 			if ( distance > object.scale.x ) {
@@ -6826,7 +6856,7 @@ THREE.EventDispatcher.prototype = {
 
 
 		} else if ( object instanceof THREE.LOD ) {
 		} else if ( object instanceof THREE.LOD ) {
 
 
-			matrixPosition.getPositionFromMatrix( object.matrixWorld );
+			matrixPosition.setFromMatrixPosition( object.matrixWorld );
 			var distance = raycaster.ray.origin.distanceTo( matrixPosition );
 			var distance = raycaster.ray.origin.distanceTo( matrixPosition );
 
 
 			intersectObject( object.getObjectForDistance( distance ), raycaster, intersects );
 			intersectObject( object.getObjectForDistance( distance ), raycaster, intersects );
@@ -7305,9 +7335,9 @@ THREE.Object3D.prototype = {
 
 
 			this.matrix.multiplyMatrices( matrix, this.matrix );
 			this.matrix.multiplyMatrices( matrix, this.matrix );
 
 
-			this.position.getPositionFromMatrix( this.matrix );
+			this.position.setFromMatrixPosition( this.matrix );
 
 
-			this.scale.getScaleFromMatrix( this.matrix );
+			this.scale.setFromMatrixScale( this.matrix );
 
 
 			m1.extractRotation( this.matrix );
 			m1.extractRotation( this.matrix );
 
 
@@ -7849,7 +7879,7 @@ THREE.Projector = function () {
 
 
 		} else {
 		} else {
 
 
-			_vector3.getPositionFromMatrix( object.matrixWorld );
+			_vector3.setFromMatrixPosition( object.matrixWorld );
 			_vector3.applyProjection( _viewProjectionMatrix );
 			_vector3.applyProjection( _viewProjectionMatrix );
 			_object.z = _vector3.z;
 			_object.z = _vector3.z;
 
 
@@ -8145,34 +8175,30 @@ THREE.Projector = function () {
 
 
 			_modelMatrix = object.matrixWorld;
 			_modelMatrix = object.matrixWorld;
 
 
-			if ( object instanceof THREE.Sprite ) {
-
-				_vector4.set( _modelMatrix.elements[12], _modelMatrix.elements[13], _modelMatrix.elements[14], 1 );
-				_vector4.applyMatrix4( _viewProjectionMatrix );
+			_vector4.set( _modelMatrix.elements[12], _modelMatrix.elements[13], _modelMatrix.elements[14], 1 );
+			_vector4.applyMatrix4( _viewProjectionMatrix );
 
 
-				var invW = 1 / _vector4.w;
+			var invW = 1 / _vector4.w;
 
 
-				_vector4.z *= invW;
+			_vector4.z *= invW;
 
 
-				if ( _vector4.z > -1 && _vector4.z < 1 ) {
+			if ( _vector4.z >= -1 && _vector4.z <= 1 ) {
 
 
-					_sprite = getNextSpriteInPool();
-					_sprite.id = object.id;
-					_sprite.x = _vector4.x * invW;
-					_sprite.y = _vector4.y * invW;
-					_sprite.z = _vector4.z;
-					_sprite.object = object;
+				_sprite = getNextSpriteInPool();
+				_sprite.id = object.id;
+				_sprite.x = _vector4.x * invW;
+				_sprite.y = _vector4.y * invW;
+				_sprite.z = _vector4.z;
+				_sprite.object = object;
 
 
-					_sprite.rotation = object.rotation;
+				_sprite.rotation = object.rotation;
 
 
-					_sprite.scale.x = object.scale.x * Math.abs( _sprite.x - ( _vector4.x + camera.projectionMatrix.elements[0] ) / ( _vector4.w + camera.projectionMatrix.elements[12] ) );
-					_sprite.scale.y = object.scale.y * Math.abs( _sprite.y - ( _vector4.y + camera.projectionMatrix.elements[5] ) / ( _vector4.w + camera.projectionMatrix.elements[13] ) );
+				_sprite.scale.x = object.scale.x * Math.abs( _sprite.x - ( _vector4.x + camera.projectionMatrix.elements[0] ) / ( _vector4.w + camera.projectionMatrix.elements[12] ) );
+				_sprite.scale.y = object.scale.y * Math.abs( _sprite.y - ( _vector4.y + camera.projectionMatrix.elements[5] ) / ( _vector4.w + camera.projectionMatrix.elements[13] ) );
 
 
-					_sprite.material = object.material;
+				_sprite.material = object.material;
 
 
-					_renderData.elements.push( _sprite );
-
-				}
+				_renderData.elements.push( _sprite );
 
 
 			}
 			}
 
 
@@ -15055,8 +15081,8 @@ THREE.LOD.prototype.update = function () {
 
 
 		if ( this.objects.length > 1 ) {
 		if ( this.objects.length > 1 ) {
 
 
-			v1.getPositionFromMatrix( camera.matrixWorld );
-			v2.getPositionFromMatrix( this.matrixWorld );
+			v1.setFromMatrixPosition( camera.matrixWorld );
+			v2.setFromMatrixPosition( this.matrixWorld );
 
 
 			var distance = v1.distanceTo( v2 );
 			var distance = v1.distanceTo( v2 );
 
 
@@ -15552,9 +15578,14 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 
 		}
 		}
 
 
-
 	};
 	};
 
 
+	// compatibility
+
+	this.clearColor = function () {};
+	this.clearDepth = function () {};
+	this.clearStencil = function () {};
+
 	this.render = function ( scene, camera ) {
 	this.render = function ( scene, camera ) {
 
 
 		if ( camera instanceof THREE.Camera === false ) {
 		if ( camera instanceof THREE.Camera === false ) {
@@ -15717,7 +15748,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 
 			if ( light instanceof THREE.DirectionalLight ) {
 			if ( light instanceof THREE.DirectionalLight ) {
 
 
-				var lightPosition = _vector3.getPositionFromMatrix( light.matrixWorld ).normalize();
+				var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ).normalize();
 
 
 				var amount = normal.dot( lightPosition );
 				var amount = normal.dot( lightPosition );
 
 
@@ -15729,7 +15760,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 
 			} else if ( light instanceof THREE.PointLight ) {
 			} else if ( light instanceof THREE.PointLight ) {
 
 
-				var lightPosition = _vector3.getPositionFromMatrix( light.matrixWorld );
+				var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld );
 
 
 				var amount = normal.dot( _vector3.subVectors( lightPosition, position ).normalize() );
 				var amount = normal.dot( _vector3.subVectors( lightPosition, position ).normalize() );
 
 
@@ -15757,8 +15788,9 @@ THREE.CanvasRenderer = function ( parameters ) {
 		var scaleX = element.scale.x * _canvasWidthHalf;
 		var scaleX = element.scale.x * _canvasWidthHalf;
 		var scaleY = element.scale.y * _canvasHeightHalf;
 		var scaleY = element.scale.y * _canvasHeightHalf;
 
 
-		_elemBox.min.set( v1.x - ( scaleX * 0.5 ), v1.y - ( scaleY * 0.5 ) );
-		_elemBox.max.set( v1.x + ( scaleX * 0.5 ), v1.y + ( scaleY * 0.5 ) );
+		var dist = 0.5 * Math.sqrt( scaleX * scaleX + scaleY * scaleY ); // allow for rotated sprite
+		_elemBox.min.set( v1.x - dist, v1.y - dist );
+		_elemBox.max.set( v1.x + dist, v1.y + dist );
 
 
 		if ( _clipBox.isIntersectionBox( _elemBox ) === false ) {
 		if ( _clipBox.isIntersectionBox( _elemBox ) === false ) {
 
 
@@ -15776,7 +15808,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 
 				_context.save();
 				_context.save();
 				_context.translate( v1.x, v1.y );
 				_context.translate( v1.x, v1.y );
-				_context.rotate( - material.rotation );
+				_context.rotate( material.rotation );
 				_context.scale( scaleX, - scaleY );
 				_context.scale( scaleX, - scaleY );
 
 
 				_context.drawImage( bitmap, 0, 0, bitmap.width, bitmap.height, - 0.5, - 0.5, 1, 1 );
 				_context.drawImage( bitmap, 0, 0, bitmap.width, bitmap.height, - 0.5, - 0.5, 1, 1 );
@@ -15788,8 +15820,8 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 
 				_context.save();
 				_context.save();
 				_context.translate( v1.x, v1.y );
 				_context.translate( v1.x, v1.y );
-				_context.rotate( - element.rotation );
-				_context.scale( scaleX, scaleY );
+				_context.rotate( material.rotation );
+				_context.scale( scaleX, - scaleY );
 				_context.fillRect( - 0.5, - 0.5, 1, 1 );
 				_context.fillRect( - 0.5, - 0.5, 1, 1 );
 				_context.restore();
 				_context.restore();
 
 
@@ -16379,6 +16411,8 @@ THREE.CanvasRenderer = function ( parameters ) {
 };
 };
 
 
 /**
 /**
+ * Shader chunks for WebLG Shader library
+ * 
  * @author alteredq / http://alteredqualia.com/
  * @author alteredq / http://alteredqualia.com/
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  * @author mikael emtinger / http://gomo.se/
  * @author mikael emtinger / http://gomo.se/
@@ -18152,6 +18186,9 @@ THREE.ShaderChunk = {
 
 
 
 
 };
 };
+/**
+ * Uniform Utilities
+ */
 
 
 THREE.UniformsUtils = {
 THREE.UniformsUtils = {
 
 
@@ -18215,6 +18252,9 @@ THREE.UniformsUtils = {
 	}
 	}
 
 
 };
 };
+/**
+ * Uniforms library for shared webgl shaders
+ */
 
 
 THREE.UniformsLib = {
 THREE.UniformsLib = {
 
 
@@ -18314,6 +18354,14 @@ THREE.UniformsLib = {
 	}
 	}
 
 
 };
 };
+/**
+ * Webgl Shader Library for three.js
+ *
+ * @author alteredq / http://alteredqualia.com/
+ * @author mrdoob / http://mrdoob.com/
+ * @author mikael emtinger / http://gomo.se/
+ */
+
 
 
 THREE.ShaderLib = {
 THREE.ShaderLib = {
 
 
@@ -19959,6 +20007,24 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	};
 	};
 
 
+	this.clearColor = function () {
+
+		_gl.clear( _gl.COLOR_BUFFER_BIT );
+
+	};
+
+	this.clearDepth = function () {
+
+		_gl.clear( _gl.DEPTH_BUFFER_BIT );
+
+	};
+
+	this.clearStencil = function () {
+
+		_gl.clear( _gl.STENCIL_BUFFER_BIT );
+
+	};
+
 	this.clearTarget = function ( renderTarget, color, depth, stencil ) {
 	this.clearTarget = function ( renderTarget, color, depth, stencil ) {
 
 
 		this.setRenderTarget( renderTarget );
 		this.setRenderTarget( renderTarget );
@@ -22852,7 +22918,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 						} else {
 						} else {
 
 
-							_vector3.getPositionFromMatrix( object.matrixWorld );
+							_vector3.setFromMatrixPosition( object.matrixWorld );
 							_vector3.applyProjection( _projScreenMatrix );
 							_vector3.applyProjection( _projScreenMatrix );
 
 
 							webglObject.z = _vector3.z;
 							webglObject.z = _vector3.z;
@@ -23980,7 +24046,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 				if ( p_uniforms.cameraPosition !== null ) {
 				if ( p_uniforms.cameraPosition !== null ) {
 
 
-					_vector3.getPositionFromMatrix( camera.matrixWorld );
+					_vector3.setFromMatrixPosition( camera.matrixWorld );
 					_gl.uniform3f( p_uniforms.cameraPosition, _vector3.x, _vector3.y, _vector3.z );
 					_gl.uniform3f( p_uniforms.cameraPosition, _vector3.x, _vector3.y, _vector3.z );
 
 
 				}
 				}
@@ -24584,8 +24650,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 				if ( ! light.visible ) continue;
 				if ( ! light.visible ) continue;
 
 
-				_direction.getPositionFromMatrix( light.matrixWorld );
-				_vector3.getPositionFromMatrix( light.target.matrixWorld );
+				_direction.setFromMatrixPosition( light.matrixWorld );
+				_vector3.setFromMatrixPosition( light.target.matrixWorld );
 				_direction.sub( _vector3 );
 				_direction.sub( _vector3 );
 				_direction.normalize();
 				_direction.normalize();
 
 
@@ -24630,7 +24696,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 				}
 				}
 
 
-				_vector3.getPositionFromMatrix( light.matrixWorld );
+				_vector3.setFromMatrixPosition( light.matrixWorld );
 
 
 				pointPositions[ pointOffset ]     = _vector3.x;
 				pointPositions[ pointOffset ]     = _vector3.x;
 				pointPositions[ pointOffset + 1 ] = _vector3.y;
 				pointPositions[ pointOffset + 1 ] = _vector3.y;
@@ -24658,7 +24724,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 				}
 				}
 
 
-				_vector3.getPositionFromMatrix( light.matrixWorld );
+				_vector3.setFromMatrixPosition( light.matrixWorld );
 
 
 				spotPositions[ spotOffset ]     = _vector3.x;
 				spotPositions[ spotOffset ]     = _vector3.x;
 				spotPositions[ spotOffset + 1 ] = _vector3.y;
 				spotPositions[ spotOffset + 1 ] = _vector3.y;
@@ -24667,7 +24733,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 				spotDistances[ spotLength ] = distance;
 				spotDistances[ spotLength ] = distance;
 
 
 				_direction.copy( _vector3 );
 				_direction.copy( _vector3 );
-				_vector3.getPositionFromMatrix( light.target.matrixWorld );
+				_vector3.setFromMatrixPosition( light.target.matrixWorld );
 				_direction.sub( _vector3 );
 				_direction.sub( _vector3 );
 				_direction.normalize();
 				_direction.normalize();
 
 
@@ -24686,7 +24752,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 				if ( ! light.visible ) continue;
 				if ( ! light.visible ) continue;
 
 
-				_direction.getPositionFromMatrix( light.matrixWorld );
+				_direction.setFromMatrixPosition( light.matrixWorld );
 				_direction.normalize();
 				_direction.normalize();
 
 
 				// skip lights with undefined direction
 				// skip lights with undefined direction
@@ -28500,7 +28566,8 @@ THREE.CurvePath.prototype.getWrapPoints = function ( oldPts, path ) {
 		// check for out of bounds?
 		// check for out of bounds?
 
 
 		var pathPt = path.getPoint( xNorm );
 		var pathPt = path.getPoint( xNorm );
-		var normal = path.getNormalVector( xNorm ).multiplyScalar( oldY );
+		var normal = path.getTangent( xNorm );
+		normal.set( -normal.y, normal.x ).multiplyScalar( oldY );
 
 
 		p.x = pathPt.x + normal.x;
 		p.x = pathPt.x + normal.x;
 		p.y = pathPt.y + normal.y;
 		p.y = pathPt.y + normal.y;
@@ -30459,7 +30526,18 @@ THREE.Animation.prototype.update = function ( deltaTimeMS ) {
 	this.currentTime += deltaTimeMS * this.timeScale;
 	this.currentTime += deltaTimeMS * this.timeScale;
 
 
 	unloopedCurrentTime = this.currentTime;
 	unloopedCurrentTime = this.currentTime;
+
+	// Mod operation fails on floats
+	// was this supposed to be in frames?
+	while ( this.currentTime > this.data.length ) {
+
+		this.currentTime -= this.data.length;
+
+	}
+
 	currentTime = this.currentTime = this.currentTime % this.data.length;
 	currentTime = this.currentTime = this.currentTime % this.data.length;
+
+	
 	frame = parseInt( Math.min( currentTime * this.data.fps, this.data.length * this.data.fps ), 10 );
 	frame = parseInt( Math.min( currentTime * this.data.fps, this.data.length * this.data.fps ), 10 );
 
 
 
 
@@ -30479,19 +30557,20 @@ THREE.Animation.prototype.update = function ( deltaTimeMS ) {
 			nextKey = animationCache.nextKey[ type ];
 			nextKey = animationCache.nextKey[ type ];
 
 
 			// switch keys?
 			// switch keys?
-
+			
 			if ( nextKey.time <= unloopedCurrentTime ) {
 			if ( nextKey.time <= unloopedCurrentTime ) {
 
 
 				// did we loop?
 				// did we loop?
 
 
-				if ( currentTime < unloopedCurrentTime ) {
+				if ( currentTime <= unloopedCurrentTime ) {
 
 
 					if ( this.loop ) {
 					if ( this.loop ) {
 
 
 						prevKey = this.data.hierarchy[ h ].keys[ 0 ];
 						prevKey = this.data.hierarchy[ h ].keys[ 0 ];
 						nextKey = this.getNextKeyWith( type, h, 1 );
 						nextKey = this.getNextKeyWith( type, h, 1 );
 
 
-						while( nextKey.time < currentTime ) {
+						// if ( nextKey.index < prevKey.index ) then we have wrapped over the end, and nextKey.time < currentTime will loop forever
+						while ( nextKey !== null && nextKey.time < currentTime && nextKey.index > prevKey.index) {
 
 
 							prevKey = nextKey;
 							prevKey = nextKey;
 							nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
 							nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
@@ -30512,7 +30591,8 @@ THREE.Animation.prototype.update = function ( deltaTimeMS ) {
 						prevKey = nextKey;
 						prevKey = nextKey;
 						nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
 						nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
 
 
-					} while( nextKey.time < currentTime )
+					} while ( nextKey !== null && nextKey.time < currentTime && nextKey.index > prevKey.index )
+					// if ( nextKey.index < prevKey.index ) then we have wrapped over the end, and nextKey.time < currentTime will loop forever
 
 
 				}
 				}
 
 
@@ -33943,9 +34023,11 @@ THREE.AxisHelper.prototype = Object.create( THREE.Line.prototype );
  *  origin - Vector3
  *  origin - Vector3
  *  length - Number
  *  length - Number
  *  hex - color in hex value
  *  hex - color in hex value
+ *  headLength - Number
+ *  headWidth - Number
  */
  */
 
 
-THREE.ArrowHelper = function ( dir, origin, length, hex ) {
+THREE.ArrowHelper = function ( dir, origin, length, hex, headLength, headWidth ) {
 
 
 	// dir is assumed to be normalized
 	// dir is assumed to be normalized
 
 
@@ -33953,6 +34035,8 @@ THREE.ArrowHelper = function ( dir, origin, length, hex ) {
 
 
 	if ( hex === undefined ) hex = 0xffff00;
 	if ( hex === undefined ) hex = 0xffff00;
 	if ( length === undefined ) length = 1;
 	if ( length === undefined ) length = 1;
+	if ( headLength === undefined ) headLength = 0.2 * length;
+	if ( headWidth === undefined ) headWidth = 0.2 * headLength;
 
 
 	this.position = origin;
 	this.position = origin;
 
 
@@ -33964,15 +34048,15 @@ THREE.ArrowHelper = function ( dir, origin, length, hex ) {
 	this.line.matrixAutoUpdate = false;
 	this.line.matrixAutoUpdate = false;
 	this.add( this.line );
 	this.add( this.line );
 
 
-	var coneGeometry = new THREE.CylinderGeometry( 0, 0.05, 0.25, 5, 1 );
-	coneGeometry.applyMatrix( new THREE.Matrix4().makeTranslation( 0, 0.875, 0 ) );
+	var coneGeometry = new THREE.CylinderGeometry( 0, 0.5, 1, 5, 1 );
+	coneGeometry.applyMatrix( new THREE.Matrix4().makeTranslation( 0, - 0.5, 0 ) );
 
 
 	this.cone = new THREE.Mesh( coneGeometry, new THREE.MeshBasicMaterial( { color: hex } ) );
 	this.cone = new THREE.Mesh( coneGeometry, new THREE.MeshBasicMaterial( { color: hex } ) );
 	this.cone.matrixAutoUpdate = false;
 	this.cone.matrixAutoUpdate = false;
 	this.add( this.cone );
 	this.add( this.cone );
 
 
 	this.setDirection( dir );
 	this.setDirection( dir );
-	this.setLength( length );
+	this.setLength( length, headLength, headWidth );
 
 
 };
 };
 
 
@@ -34009,9 +34093,17 @@ THREE.ArrowHelper.prototype.setDirection = function () {
 
 
 }();
 }();
 
 
-THREE.ArrowHelper.prototype.setLength = function ( length ) {
+THREE.ArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) {
+
+	if ( headLength === undefined ) headLength = 0.2 * length;
+	if ( headWidth === undefined ) headWidth = 0.2 * headLength;
+
+	this.line.scale.set( 1, length, 1 );
+	this.line.updateMatrix();
 
 
-	this.scale.set( length, length, length );
+	this.cone.scale.set( headWidth, headLength, headWidth );
+	this.cone.position.y = length;
+	this.cone.updateMatrix();
 
 
 };
 };
 
 
@@ -34382,8 +34474,8 @@ THREE.DirectionalLightHelper.prototype.update = function () {
 
 
 	return function () {
 	return function () {
 
 
-		v1.getPositionFromMatrix( this.light.matrixWorld );
-		v2.getPositionFromMatrix( this.light.target.matrixWorld );
+		v1.setFromMatrixPosition( this.light.matrixWorld );
+		v2.setFromMatrixPosition( this.light.target.matrixWorld );
 		v3.subVectors( v2, v1 );
 		v3.subVectors( v2, v1 );
 
 
 		this.lightPlane.lookAt( v3 );
 		this.lightPlane.lookAt( v3 );
@@ -34566,7 +34658,7 @@ THREE.HemisphereLightHelper.prototype.update = function () {
 		this.colors[ 0 ].copy( this.light.color ).multiplyScalar( this.light.intensity );
 		this.colors[ 0 ].copy( this.light.color ).multiplyScalar( this.light.intensity );
 		this.colors[ 1 ].copy( this.light.groundColor ).multiplyScalar( this.light.intensity );
 		this.colors[ 1 ].copy( this.light.groundColor ).multiplyScalar( this.light.intensity );
 
 
-		this.lightSphere.lookAt( vector.getPositionFromMatrix( this.light.matrixWorld ).negate() );
+		this.lightSphere.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() );
 		this.lightSphere.geometry.colorsNeedUpdate = true;
 		this.lightSphere.geometry.colorsNeedUpdate = true;
 
 
 	}
 	}
@@ -34696,8 +34788,8 @@ THREE.SpotLightHelper.prototype.update = function () {
 
 
 		this.cone.scale.set( coneWidth, coneWidth, coneLength );
 		this.cone.scale.set( coneWidth, coneWidth, coneLength );
 
 
-		vector.getPositionFromMatrix( this.light.matrixWorld );
-		vector2.getPositionFromMatrix( this.light.target.matrixWorld );
+		vector.setFromMatrixPosition( this.light.matrixWorld );
+		vector2.setFromMatrixPosition( this.light.target.matrixWorld );
 
 
 		this.cone.lookAt( vector2.sub( vector ) );
 		this.cone.lookAt( vector2.sub( vector ) );
 
 
@@ -34915,34 +35007,110 @@ THREE.WireframeHelper = function ( object ) {
 	var sortFunction = function ( a, b ) { return a - b };
 	var sortFunction = function ( a, b ) { return a - b };
 
 
 	var keys = [ 'a', 'b', 'c', 'd' ];
 	var keys = [ 'a', 'b', 'c', 'd' ];
-	var geometry = new THREE.Geometry();
+	var geometry = new THREE.BufferGeometry();
+	var numEdges = 0;
 
 
-	var vertices = object.geometry.vertices;
-	var faces = object.geometry.faces;
+	if ( object.geometry instanceof THREE.Geometry ) {
 
 
-	for ( var i = 0, l = faces.length; i < l; i ++ ) {
+		var vertices = object.geometry.vertices;
+		var faces = object.geometry.faces;
 
 
-		var face = faces[ i ];
+		// allocate maximal size
+		var edges = new Uint32Array(6 * faces.length);
+
+		for ( var i = 0, l = faces.length; i < l; i ++ ) {
+
+			var face = faces[ i ];
+
+			for ( var j = 0; j < 3; j ++ ) {
+
+				edge[ 0 ] = face[ keys[ j ] ];
+				edge[ 1 ] = face[ keys[ ( j + 1 ) % 3 ] ];
+				edge.sort( sortFunction );
+
+				var key = edge.toString();
 
 
-		for ( var j = 0; j < 3; j ++ ) {
+				if ( hash[ key ] === undefined ) {
 
 
-			edge[ 0 ] = face[ keys[ j ] ];
-			edge[ 1 ] = face[ keys[ ( j + 1 ) % 3 ] ];
-			edge.sort( sortFunction );
+					edges[ 2 * numEdges ] = edge[ 0 ];
+					edges[ 2 * numEdges + 1 ] = edge[ 1 ];
+					hash[ key ] = true;
+					numEdges ++;
 
 
-			var key = edge.toString();
+				}
+
+			}
+
+		}
+
+		geometry.addAttribute( 'position', Float32Array, 2 * numEdges , 3 );
+		var coords = geometry.attributes.position.array;
+
+		for ( var i = 0, l = numEdges; i < l; i ++ ) {
+
+			for ( var j = 0; j < 2; j ++ ) {
+
+				var vertex = vertices[ edges [ 2 * i + j] ];
+
+				var index = 6 * i + 3 * j;
+				coords[ index + 0 ] = vertex.x;
+				coords[ index + 1 ] = vertex.y;
+				coords[ index + 2 ] = vertex.z;
+
+			}
+
+		}
+
+	} else {
 
 
-			if ( hash[ key ] === undefined ) {
+		var vertices = object.geometry.attributes.position.array;
+		var faces = object.geometry.attributes.index.array;
 
 
-				geometry.vertices.push( vertices[ edge[ 0 ] ] );
-				geometry.vertices.push( vertices[ edge[ 1 ] ] );
+		// allocate maximal size
+		var edges = new Uint32Array(2 * faces.length);
 
 
-				hash[ key ] = true;
+		for ( var i = 0, l = faces.length / 3; i < l; i ++ ) {
+
+			for ( var j = 0; j < 3; j ++ ) {
+
+				var index = i * 3;
+
+				edge[ 0 ] = faces[ index + j ];
+				edge[ 1 ] = faces[ index + ( j + 1 ) % 3 ];
+				edge.sort( sortFunction );
+
+				var key = edge.toString();
+
+				if ( hash[ key ] === undefined ) {
+
+					edges[ 2 * numEdges ] = edge[ 0 ];
+					edges[ 2 * numEdges + 1 ] = edge[ 1 ];
+					hash[ key ] = true;
+					numEdges ++;
+
+				}
 
 
 			}
 			}
 
 
 		}
 		}
 
 
+		geometry.addAttribute( 'position', Float32Array, 2 * numEdges , 3 );
+
+		var coords = geometry.attributes.position.array;
+
+		for ( var i = 0, l = numEdges; i < l; i ++ ) {
+
+			for ( var j = 0; j < 2; j ++ ) {
+
+				var index = 6 * i + 3 * j;
+				var index2 = 3 * edges[ 2 * i + j];
+				coords[ index + 0 ] = vertices[ index2 ];
+				coords[ index + 1 ] = vertices[ index2 + 1 ];
+				coords[ index + 2 ] = vertices[ index2 + 2 ];
+
+			}
+
+		}
 	}
 	}
 
 
 	THREE.Line.call( this, geometry, new THREE.LineBasicMaterial( { color: 0xffffff } ), THREE.LinePieces );
 	THREE.Line.call( this, geometry, new THREE.LineBasicMaterial( { color: 0xffffff } ), THREE.LinePieces );
@@ -35870,8 +36038,8 @@ THREE.ShadowMapPlugin = function () {
 			shadowMatrix = light.shadowMatrix;
 			shadowMatrix = light.shadowMatrix;
 			shadowCamera = light.shadowCamera;
 			shadowCamera = light.shadowCamera;
 
 
-			shadowCamera.position.getPositionFromMatrix( light.matrixWorld );
-			_matrixPosition.getPositionFromMatrix( light.target.matrixWorld );
+			shadowCamera.position.setFromMatrixPosition( light.matrixWorld );
+			_matrixPosition.setFromMatrixPosition( light.target.matrixWorld );
 			shadowCamera.lookAt( _matrixPosition );
 			shadowCamera.lookAt( _matrixPosition );
 			shadowCamera.updateMatrixWorld();
 			shadowCamera.updateMatrixWorld();
 
 

File diff suppressed because it is too large
+ 37 - 35
build/three.min.js


+ 5 - 5
docs/api/materials/Material.html

@@ -35,7 +35,7 @@
 
 
 		<h3>.[page:Float opacity]</h3>
 		<h3>.[page:Float opacity]</h3>
 		<div>
 		<div>
-		Float in the range of 0.0 - 1.0 indicating how see through the material is.
+		Float in the range of 0.0 - 1.0 indicating how transparent the material is.
 		A value of 0.0 indicates fully transparent, 1.0 is fully opaque. If
 		A value of 0.0 indicates fully transparent, 1.0 is fully opaque. If
 		*transparent* is not set to true for the material, the material will remain
 		*transparent* is not set to true for the material, the material will remain
 		fully opaque and this value will only affect its color.
 		fully opaque and this value will only affect its color.
@@ -44,9 +44,9 @@
 
 
 		<h3>.[page:Boolean transparent]</h3>
 		<h3>.[page:Boolean transparent]</h3>
 		<div>
 		<div>
-		Defines whether this material is transparent. This has an effect on rendering,
-		as transparent objects need an special treatment, and are rendered after the
-		non transparent objects. For a working example of this behaviour, check the
+		Defines whether this material is transparent. This has an effect on rendering
+		as transparent objects need special treatment and are rendered after 
+		non-transparent objects. For a working example of this behaviour, check the
 		[page:WebGLRenderer WebGLRenderer] code.<br />
 		[page:WebGLRenderer WebGLRenderer] code.<br />
 		When set to true, the extent to which the material is transparent is
 		When set to true, the extent to which the material is transparent is
 		controlled by setting *opacity*.
 		controlled by setting *opacity*.
@@ -126,7 +126,7 @@
 
 
 		<h3>.[page:Boolean needsUpdate]</h3>
 		<h3>.[page:Boolean needsUpdate]</h3>
 		<div>
 		<div>
-		Specifies that the material needs to be updated, WebGL wise. Set it to true if you made changes that need to be reflected in WebGL.
+		Specifies that the material needs to be updated at the WebGL level. Set it to true if you made changes that need to be reflected in WebGL.
 		</div>
 		</div>
 		<div>
 		<div>
 		This property is automatically set to *true* when instancing a new material.
 		This property is automatically set to *true* when instancing a new material.

+ 21 - 6
docs/api/materials/ShaderMaterial.html

@@ -17,12 +17,27 @@
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
 
 
-		<h3>[name]([page:todo parameters])</h3>
+		<h3>[name]([page:Object parameters])</h3>
 		<div>
 		<div>
-		parameters -- todo
+		parameters -- An object containing various parameters setting up shaders and their uniforms.
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		<br>
+		Example:<br>
+		<br>
+		uniforms = {
+			time: { type: "f", value: 1.0 },
+			resolution: { type: "v2", value: new THREE.Vector2() }
+		};
+
+		material = new THREE.ShaderMaterial( {
+
+			uniforms: uniforms,
+			vertexShader: document.getElementById( 'vertexShader' ).textContent,
+			fragmentShader: document.getElementById( 'fragmentShader' ).textContent
+
+		} );
+
 		</div>
 		</div>
 
 
 
 
@@ -32,17 +47,17 @@
 
 
 		<h3>.[page:object uniforms]</h3>
 		<h3>.[page:object uniforms]</h3>
 		<div>
 		<div>
-		todo
+		Uniforms defined inside GLSL shader code.
 		</div> 
 		</div> 
 
 
 		<h3>.[page:string fragmentShader]</h3>
 		<h3>.[page:string fragmentShader]</h3>
 		<div>
 		<div>
-		todo
+		Fragment shader GLSL code.  This is the actual code for the shader.  In the example above the code is retrieved from DOM elements emnbedded directly in the page although other methods can be used including specifying a string directly.  
 		</div> 
 		</div> 
 
 
 		<h3>.[page:string vertexShader]</h3>
 		<h3>.[page:string vertexShader]</h3>
 		<div>
 		<div>
-		todo
+		Vertex shader GLSL code.  This is the actual code for the shader.  In the example above the code is retrieved from DOM elements emnbedded directly in the page although other methods can be used including specifying a string directly.  
 		</div> 
 		</div> 
 
 
 		<h3>.[page:boolean morphTargets]</h3>
 		<h3>.[page:boolean morphTargets]</h3>

+ 5 - 3
docs/api/math/Box2.html

@@ -103,12 +103,14 @@
 		lower bounds.
 		lower bounds.
 		</div>
 		</div>
 
 
-		<h3>.getParameter([page:Vector2 point]) [page:Vector2]</h3>
+		<h3>.getParameter([page:Vector2 point], [page:Vector2 optionalTarget]) [page:Vector2]</h3>
 		<div>
 		<div>
-		point -- Point to parametrize.
+		point -- [page:Vector2]<br/>
+		optionalTarget -- [page:Vector2]<br/>
+		
 		</div>
 		</div>
 		<div>
 		<div>
-		Returns point as a proportion of this box's width and height.
+		Returns a point as a proportion of this box's width and height.
 		</div>
 		</div>
 
 
 		<h3>.expandByScalar([page:float scalar]) [page:Box2 this]</h3>
 		<h3>.expandByScalar([page:float scalar]) [page:Box2 this]</h3>

+ 68 - 65
docs/api/math/Box3.html

@@ -48,15 +48,15 @@
 		max -- Lower (x, y, z) boundary of this box.
 		max -- Lower (x, y, z) boundary of this box.
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Sets the lower and upper (x, y, z) boundaries of this box.
 		</div>
 		</div>
 
 
 		<h3>.applyMatrix4([page:Matrix4 matrix]) [page:Box3 this]</h3>
 		<h3>.applyMatrix4([page:Matrix4 matrix]) [page:Box3 this]</h3>
 		<div>
 		<div>
-		matrix -- Transform the box with a matrix.
+		matrix -- [page:Matrix4].
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Transform the box with a Matrix4.
 		</div>
 		</div>
 
 
 		<h3>.expandByPoint([page:Vector3 point]) [page:Box3 this]</h3>
 		<h3>.expandByPoint([page:Vector3 point]) [page:Box3 this]</h3>
@@ -64,165 +64,168 @@
 		Expands the box outwards by the point. It takes the min and max values of the box.
 		Expands the box outwards by the point. It takes the min and max values of the box.
 		</div>
 		</div>
 
 
-		<h3>.clampPoint([page:Vector3 point], [page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.clampPoint([page:Vector3 point], [page:Vector3 optionalTarget]) [page:Vector3]</h3>
 		<div>
 		<div>
-		point -- todo <br />
-		optionalTarget -- todo
+		point -- [page:Vector3] <br />
+		optionalTarget -- [page:Vector3] An optional target point.
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Clamp a point within the min and max boundaries of the box. Returns either a new point or the modified passed target.
 		</div>
 		</div>
 
 
-		<h3>.isIntersectionBox([page:todo box]) [page:todo]</h3>
+		<h3>.isIntersectionBox([page:Box3 box]) [page:Boolean]</h3>
 		<div>
 		<div>
-		box -- todo
+		box -- [page:Box3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Return whether or not the passed box intersects with this Box3.
 		</div>
 		</div>
 
 
-		<h3>.setFromPoints([page:todo points]) [page:todo]</h3>
+		<h3>.setFromPoints([page:Array points])</h3>
 		<div>
 		<div>
-		points -- todo
+		points -- [page:Array] of [page:Vector3] points
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Sets this box to the min value and max value of all the points in the array. If the array is empty, then it sets the box as empty.
 		</div>
 		</div>
 
 
-		<h3>.size([page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.size([page:Vector3 optionalTarget]) [page:Vector3]</h3>
 		<div>
 		<div>
-		optionalTarget -- todo
+		optionalTarget -- [page:Vector3] (optional)
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns either a new Vector3 or the target Vector3 that represents the size of the box from the min point to max point.
 		</div>
 		</div>
 
 
-		<h3>.union([page:todo box]) [page:todo]</h3>
+		<h3>.union([page:Box3 box]) [page:Box3 this]</h3>
 		<div>
 		<div>
-		box -- todo
+		box -- [page:Box3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Sets the box's min and max boundaries to union of the two boxes.
 		</div>
 		</div>
 
 
-		<h3>.getParameter([page:todo point]) [page:todo]</h3>
+		<h3>.getParameter([page:Vector3 point], [page:Vector3 optionalTarget]) [page:Vector3]</h3>
 		<div>
 		<div>
-		point -- todo
+		point -- [page:Vector3]<br/>
+		optionalTarget -- [page:Vector3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns a point as a proportion of this box's width, height, and depth. If the point is contained by the box the x, y, and z of the returned vector will be between 0 and 1.
 		</div>
 		</div>
 
 
-		<h3>.expandByScalar([page:todo scalar]) [page:todo]</h3>
+		<h3>.expandByScalar([page:Float scalar]) [page:Box3 this]</h3>
 		<div>
 		<div>
-		scalar -- todo
+		scalar -- [page:Float] representing the distance to expand
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Expands or contracts the box by adding the scalar value to the box's min and max vectors.
 		</div>
 		</div>
 
 
-		<h3>.intersect([page:todo box]) [page:todo]</h3>
+		<h3>.intersect([page:Box3 box]) [page:Box3 this]</h3>
 		<div>
 		<div>
-		box -- todo
+		box -- [page:Box3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns the intersection of the two boxes, setting the upper bound of this box to the lesser of the two boxes' upper bounds and the lower bound of this box to the greater of the two boxes' lower bounds.
+ 
 		</div>
 		</div>
 
 
-		<h3>.containsBox([page:todo box]) [page:todo]</h3>
+		<h3>.containsBox([page:Box3 box]) [page:Boolean]</h3>
 		<div>
 		<div>
-		box -- todo
+		box -- [page:Box3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns true if this box includes the entirety of box. If this and box overlap exactly, this function also returns true.
+ 
 		</div>
 		</div>
 
 
-		<h3>.translate([page:todo offset]) [page:todo]</h3>
+		<h3>.translate([page:Vector3 offset]) [page:Box3 this]</h3>
 		<div>
 		<div>
-		offset -- todo
+		offset -- [page:Vector3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Translates the box the distance of the offset.
 		</div>
 		</div>
 
 
-		<h3>.empty() [page:todo]</h3>
+		<h3>.empty() [page:Boolean]</h3>
 		<div>
 		<div>
-		todo
+		Checks to see if the box is empty. If the lower and upper bounds of the box are equal, this function still returns false as the box would still contain one point.
 		</div>
 		</div>
 
 
-		<h3>.clone() [page:todo]</h3>
+		<h3>.clone() [page:Box3]</h3>
 		<div>
 		<div>
-		todo
+		Returns a copy of this box.
 		</div>
 		</div>
 
 
-		<h3>.equals([page:todo box]) [page:todo]</h3>
+		<h3>.equals([page:Box3 box]) [page:Boolean]</h3>
 		<div>
 		<div>
-		box -- todo
+		box -- [page:Box3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns true if the boes share the same lower and upper bounds. 
 		</div>
 		</div>
 
 
-		<h3>.expandByVector([page:todo vector]) [page:todo]</h3>
+		<h3>.expandByVector([page:Vector3 vector]) [page:Box3 this]</h3>
 		<div>
 		<div>
-		vector -- todo
+		vector -- [page:Vector3] representing the amount to expand this box in each dimension.
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Adds the passed vector to the upper boundary, and subtracts it from the lower boundary.
 		</div>
 		</div>
 
 
-		<h3>.copy([page:todo box]) [page:todo]</h3>
+		<h3>.copy([page:Box3 box]) [page:Box3 this]</h3>
 		<div>
 		<div>
-		box -- todo
+		box -- [page:Box3] to copy.
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Copies the values of the passed box to this box.
 		</div>
 		</div>
 
 
-		<h3>.makeEmpty() [page:todo]</h3>
+		<h3>.makeEmpty() [page:Box3 this]</h3>
 		<div>
 		<div>
-		todo
+		Makes this box empty so that it cannot contain any points.
 		</div>
 		</div>
 
 
-		<h3>.center([page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.center([page:Vector3 optionalTarget]) [page:Vector3]</h3>
 		<div>
 		<div>
-		optionalTarget -- todo
+		optionalTarget -- [page:Vector3] If specified, the result will be copied here.
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns the center point of this box. 
 		</div>
 		</div>
 
 
-		<h3>.getBoundingSphere([page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.getBoundingSphere([page:Sphere optionalTarget]) [page:Sphere]</h3>
 		<div>
 		<div>
-		optionalTarget -- todo
+		optionalTarget -- [page:Sphere]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns a bounding sphere.
 		</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 distance from any edge of this box to the specified point. If the point lies inside of this box, the distance will be 0.
 		</div>
 		</div>
 
 
-		<h3>.containsPoint([page:todo point]) [page:todo]</h3>
+		<h3>.containsPoint([page:Vector3 point]) [page:Boolean]</h3>
 		<div>
 		<div>
-		point -- todo
+		point -- [page:Vector3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns true if the specified point lies within the boundaries of this box.
 		</div>
 		</div>
 
 
-		<h3>.setFromCenterAndSize([page:todo center], [page:todo size]) [page:todo]</h3>
+		<h3>.setFromCenterAndSize([page:Vector3 center], [page:Vector3 size]) [page:Box3 this]</h3>
 		<div>
 		<div>
-		center -- todo <br />
-		size -- todo
+		center -- [page:Vector3] representing the center position.<br />
+		size -- [page:Vector3] representing the dimensions of the box.
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Sets this box based on a center vector, and width, height, and depth vector.
 		</div>
 		</div>
 
 
 		<h2>Source</h2>
 		<h2>Source</h2>

+ 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>

+ 50 - 56
docs/api/math/Line3.html

@@ -2,26 +2,26 @@
 <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>
 
 
-		<div class="desc">todo</div>
+		<div class="desc">A geometric line segment represented by a start and end point.</div>
 
 
 
 
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
 
 
-		<h3>[name]([page:todo start], [page:todo end])</h3>
+		<h3>[name]([page:Vector3 start], [page:Vector3 end])</h3>
 		<div>
 		<div>
-		start -- todo <br />
-		end -- todo
+		start -- [page:Vector3] Start of the line segment<br />
+		end -- [page:Vector3] End of the line segment
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		The start and end vectors default to origin vectors if none are set.
 		</div>
 		</div>
 
 
 
 
@@ -30,109 +30,103 @@
 
 
 
 
 		<h3>.[page:Vector3 start]</h3>
 		<h3>.[page:Vector3 start]</h3>
-		<div>
-		todo
-		</div> 
 
 
 		<h3>.[page:Vector3 end]</h3>
 		<h3>.[page:Vector3 end]</h3>
-		<div>
-		todo
-		</div> 
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 
 
 
 
 
 
-		<h3>.closestPointToPointParameter([page:todo point], [page:todo clampToLine]) [page:todo]</h3>
+		<h3>.set([page:Vector3 start], [page:Vector3 end]) [page:Line3]</h3>
 		<div>
 		<div>
-		point -- todo <br />
-		clampToLine -- todo
+		start -- [page:Vector3] <br />
+		end -- [page:Vector3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Sets the start and end values by copying the provided vectors.
 		</div>
 		</div>
 
 
-		<h3>.distanceSq() [page:todo]</h3>
+		<h3>.copy([page:Line3 line]) [page:Line3]</h3>
 		<div>
 		<div>
-		todo
+		line -- [page:Line3]
 		</div>
 		</div>
-
-		<h3>.copy([page:todo line]) [page:todo]</h3>
 		<div>
 		<div>
-		line -- todo
+		Copies the passed line's start and end vectors to this line.
 		</div>
 		</div>
+
+		<h3>.clone() [page:Line3]</h3>
 		<div>
 		<div>
-		todo
+		Return a new copy of this [page:Line3].
 		</div>
 		</div>
 
 
-		<h3>.applyMatrix4([page:todo matrix]) [page:todo]</h3>
+		<h3>.equals([page:Line3 line]) [page:Boolean]</h3>
 		<div>
 		<div>
-		matrix -- todo
+		line -- [page:Line3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
-		</div>
 
 
-		<h3>.distance() [page:todo]</h3>
+		<h3>.distance() [page:Float]</h3>
 		<div>
 		<div>
-		todo
+		Returns the length of the line segment.
 		</div>
 		</div>
-
-		<h3>.clone() [page:todo]</h3>
+		Returns true if both line's start and end points are equal.
+		</div>
+		
+		<h3>.distanceSq() [page:Float]</h3>
 		<div>
 		<div>
-		todo
+		Returns the line segment's length squared.
 		</div>
 		</div>
 
 
-		<h3>.equals([page:todo line]) [page:todo]</h3>
+		<h3>.applyMatrix4([page:Matrix4 matrix]) [page:Line3 this]</h3>
 		<div>
 		<div>
-		line -- todo
+		matrix -- [page:Matrix4]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Apply a matrix transform to the line segment.
 		</div>
 		</div>
 
 
-		<h3>.set([page:todo start], [page:todo end]) [page:todo]</h3>
+		<h3>.at([page:Float t], [page:Vector3 optionalTarget]) [page:Vector]</h3>
 		<div>
 		<div>
-		start -- todo <br />
-		end -- todo
+		t -- [page:Float] Use values 0-1 to return a result on the line segment. <br />
+		optionalTarget -- [page:Vector] Optional target to set the result.
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Return a vector at a certain position along the line. When t = 0, it returns the start vector, and when t=1 it returns the end vector.
 		</div>
 		</div>
-
-		<h3>.at([page:todo t], [page:todo optionalTarget]) [page:todo]</h3>
+		
+		<h3>.center([page:Vector3 optionalTarget]) [page:Vector3]</h3>
 		<div>
 		<div>
-		t -- todo <br />
-		optionalTarget -- todo
+		optionalTarget -- [page:Vector3] Optional target to set the result.
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Return the center of the line segment.
 		</div>
 		</div>
 
 
-		<h3>.delta([page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.delta([page:Vector3 optionalTarget]) [page:Vector3]</h3>
 		<div>
 		<div>
-		optionalTarget -- todo
+		optionalTarget -- [page:Vector3] Optional target to set the result.
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns the delta vector of the line segment, or the end vector minus the start vector.
 		</div>
 		</div>
 
 
-		<h3>.closestPointToPoint([page:todo point], [page:todo clampToLine], [page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.closestPointToPoint([page:Vector3 point], [page:Boolean clampToLine], [page:Vector3 optionalTarget]) [page:Vector3]</h3>
 		<div>
 		<div>
-		point -- todo <br />
-		clampToLine -- todo <br />
-		optionalTarget -- todo
+		point -- [page:Vector3] <br />
+		clampToLine -- [page:Boolean] <br />
+		optionalTarget -- [page:Vector3] Optional target to set the result.
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns the closets point on the line. If clamp to line is true, then the returned value will be clamped to the line segment.
 		</div>
 		</div>
 
 
-		<h3>.center([page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.closestPointToPointParameter([page:Vector3 point], [page:Boolean clampToLine]) [page:Float]</h3>
 		<div>
 		<div>
-		optionalTarget -- todo
+		point -- [page:Vector3] <br />
+		clampToLine -- [page:Boolean]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns a point parameter based on the closest point as projected on the line segement. If clamp to line is true, then the returned value will be between 0 and 1.
 		</div>
 		</div>
 
 
 		<h2>Source</h2>
 		<h2>Source</h2>

+ 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) pre-computed normal [Page:Matrix3] of the Matrix4 to apply
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Apply a Matrix4 to the plane. The second parameter is optional.
+		
+		<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>

+ 48 - 57
docs/api/math/Sphere.html

@@ -9,139 +9,130 @@
 	<body>
 	<body>
 		<h1>[name]</h1>
 		<h1>[name]</h1>
 
 
-		<div class="desc">todo</div>
+		<div class="desc">A geometric sphere defined by a center position and radius.</div>
 
 
 
 
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
 
 
-		<h3>[name]([page:todo center], [page:todo radius])</h3>
+		<h3>[name]([page:Vector3 center], [page:Float radius])</h3>
 		<div>
 		<div>
-		center -- todo <br />
-		radius -- todo
-		</div>
-		<div>
-		todo
+		center -- [page:Vector3] <br />
+		radius -- [page:Float]
 		</div>
 		</div>
-
+		
 
 
 		<h2>Properties</h2>
 		<h2>Properties</h2>
 
 
 
 
-
-		<h3>.[page:number radius]</h3>
-		<div>
-		todo
-		</div> 
-
 		<h3>.[page:Vector3 center]</h3>
 		<h3>.[page:Vector3 center]</h3>
-		<div>
-		todo
-		</div> 
-
+		
+		<h3>.[page:Float radius]</h3>
+		
+		
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 
 
 
 
 
 
-		<h3>.set([page:todo center], [page:todo radius]) [page:todo]</h3>
+		<h3>.set([page:Vector3 center], [page:Float radius]) [page:this:Sphere]</h3>
 		<div>
 		<div>
-		center -- todo <br />
-		radius -- todo
+		center -- [page:Vector3] <br />
+		radius -- [page:Float]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Sets the center and radius.
 		</div>
 		</div>
 
 
-		<h3>.applyMatrix4([page:todo matrix]) [page:todo]</h3>
+		<h3>.applyMatrix4([page:Matrix4 matrix]) [page:Sphere this]</h3>
 		<div>
 		<div>
-		matrix -- todo
+		matrix -- [page:Matrix4]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Transforms this sphere with the provided [page:Matrix4].
 		</div>
 		</div>
 
 
-		<h3>.clampPoint([page:todo point], [page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.clampPoint([page:Vector3 point], [page:Vector3 optionalTarget]) [page:Vector3]</h3>
 		<div>
 		<div>
-		point -- todo <br />
-		optionalTarget -- todo
+		point -- [page:Vector3] The point to clamp <br />
+		optionalTarget -- [page:Vector3] The optional target point to return
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Clamps a point within the sphere. If the point is is outside the sphere, it will clamp it to the closets point on the edge of the sphere.
 		</div>
 		</div>
 
 
-		<h3>.translate([page:todo offset]) [page:todo]</h3>
+		<h3>.translate([page:Vector3 offset]) [page:Sphere this]</h3>
 		<div>
 		<div>
-		offset -- todo
+		offset -- [page:Vector3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Translate the sphere's center by the provided offset vector.
 		</div>
 		</div>
 
 
-		<h3>.clone() [page:todo]</h3>
+		<h3>.clone() [page:Sphere]</h3>
 		<div>
 		<div>
-		todo
+		Provides a new copy of the sphere.
 		</div>
 		</div>
 
 
-		<h3>.equals([page:todo sphere]) [page:todo]</h3>
+		<h3>.equals([page:Sphere sphere]) [page:Boolean]</h3>
 		<div>
 		<div>
-		sphere -- todo
+		sphere -- [page:Sphere]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Checks to see if the two spheres' centers and radii are equal.
 		</div>
 		</div>
 
 
-		<h3>.setFromPoints([page:todo points], [page:Vector3 optionalCenter]) [page:todo]</h3>
+		<h3>.setFromPoints([page:Array points], [page:Vector3 optionalCenter]) [page:Sphere this]</h3>
 		<div>
 		<div>
-		points -- list of [page:Vector3 vector] positions.<br />  
-		optionalCenter -- optional position for the sphere's center.<br />
+		points -- [page:Array] of [page:Vector3] positions.<br />  
+		optionalCenter -- Optional [page:Vector3] position for the sphere's center.<br />
 		</div>
 		</div>
 		<div>
 		<div>
 		Computes the minimum bounding sphere for *points*. If *optionalCenter* is given, it is used as the sphere's center. Otherwise, the center of the axis-aligned bounding box encompassing *points* is calculated.
 		Computes the minimum bounding sphere for *points*. If *optionalCenter* is given, it is used as the sphere's center. Otherwise, the center of the axis-aligned bounding box encompassing *points* is calculated.
 		</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 closest distance from the boundary of the sphere to the point. If the sphere contains the point, the distance will be negative.
 		</div>
 		</div>
 
 
-		<h3>.getBoundingBox([page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.getBoundingBox([page:Box optionalTarget]) [page:Box]</h3>
 		<div>
 		<div>
-		optionalTarget -- todo
+		optionalTarget -- [page:Box]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Returns a bounding box for the sphere, optionally setting a provided box target.
 		</div>
 		</div>
 
 
-		<h3>.containsPoint([page:todo point]) [page:todo]</h3>
+		<h3>.containsPoint([page:Vector3 point]) [page:Boolean]</h3>
 		<div>
 		<div>
-		point -- todo
+		point -- [page:Vector3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Checks to see if the sphere contains the provided point inclusive of the edge of the sphere.
 		</div>
 		</div>
 
 
-		<h3>.copy([page:todo sphere]) [page:todo]</h3>
+		<h3>.copy([page:Sphere sphere]) [page:Sphere]</h3>
 		<div>
 		<div>
-		sphere -- todo
+		sphere -- [page:Sphere] to copy
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Copies the values of the passed sphere to this sphere.
 		</div>
 		</div>
 
 
-		<h3>.intersectsSphere([page:todo sphere]) [page:todo]</h3>
+		<h3>.intersectsSphere([page:Sphere sphere]) [page:Boolean]</h3>
 		<div>
 		<div>
-		sphere -- todo
+		sphere -- [page:Sphere]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Checks to see if two spheres intersect.
 		</div>
 		</div>
 
 
-		<h3>.empty() [page:todo]</h3>
+		<h3>.empty() [page:Boolean]</h3>
 		<div>
 		<div>
-		todo
+		Checks to see if the sphere is empty (the radius set to 0).
 		</div>
 		</div>
 
 
 		<h2>Source</h2>
 		<h2>Source</h2>

+ 51 - 50
docs/api/math/Triangle.html

@@ -9,20 +9,20 @@
 	<body>
 	<body>
 		<h1>[name]</h1>
 		<h1>[name]</h1>
 
 
-		<div class="desc">todo</div>
+		<div class="desc">A geometric triangle as defined by three vectors.</div>
 
 
 
 
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
 
 
-		<h3>[name]([page:todo a], [page:todo b], [page:todo c])</h3>
+		<h3>[name]([page:Vector3 a], [page:Vector3 b], [page:Vector3 c])</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
+		Sets the triangle's vectors to the passed vectors.
 		</div>
 		</div>
 
 
 
 
@@ -32,109 +32,110 @@
 
 
 		<h3>.[page:Vector3 a]</h3>
 		<h3>.[page:Vector3 a]</h3>
 		<div>
 		<div>
-		todo
-		</div> 
-
+		The first [page:Vector3] of the triangle.
+		</div>
+		
 		<h3>.[page:Vector3 c]</h3>
 		<h3>.[page:Vector3 c]</h3>
 		<div>
 		<div>
-		todo
-		</div> 
+		The second [page:Vector3] of the triangle.
+		</div>
 
 
 		<h3>.[page:Vector3 b]</h3>
 		<h3>.[page:Vector3 b]</h3>
 		<div>
 		<div>
-		todo
-		</div> 
+		The third [page:Vector3] of the triangle.
+		</div>
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 
 
 
 
 
 
-		<h3>.setFromPointsAndIndices([page:todo points], [page:todo i0], [page:todo i1], [page:todo i2]) [page:todo]</h3>
+		<h3>.setFromPointsAndIndices([page:Array points], [page:Integer i0], [page:Integer i1], [page:Integer i2]) [page:Triangle this]</h3>
 		<div>
 		<div>
-		points -- todo <br />
-		i0 -- todo <br />
-		i1 -- todo <br />
-		i2 -- todo
+		points -- [page:Array] of [page:Vector3]s <br />
+		i0 -- [page:Integer] index <br />
+		i1 -- [page:Integer] index <br />
+		i2 -- [page:Integer] index
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Sets the triangle's vectors to the vectors in the array.
 		</div>
 		</div>
 
 
-		<h3>.set([page:todo a], [page:todo b], [page:todo c]) [page:todo]</h3>
+		<h3>.set([page:Vector3 a], [page:Vector3 b], [page:Vector3 c]) [page:Triangle 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
+		Sets the triangle's vectors to the passed vectors.
 		</div>
 		</div>
 
 
-		<h3>.normal([page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.normal([page:Vector3 optionalTarget]) [page:Vector3]</h3>
 		<div>
 		<div>
-		optionalTarget -- todo
+		optionalTarget -- Optional [page:Vector3] target to set the result.
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Return the calculated normal of the triangle.
 		</div>
 		</div>
 
 
-		<h3>.barycoordFromPoint([page:todo point], [page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.barycoordFromPoint([page:Vector3 point], [page:Vector3 optionalTarget]) [page:Vector3]</h3>
 		<div>
 		<div>
-		point -- todo <br />
-		optionalTarget -- todo
+		point -- [page:Vector3] <br />
+		optionalTarget -- Optional [page:Vector3] target to set the result.
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Return a barycentric coordinate from the given vector. <br/><br/>
+		[link:http://commons.wikimedia.org/wiki/File:Barycentric_coordinates_1.png](Picture of barycentric coordinates)
 		</div>
 		</div>
 
 
-		<h3>.clone() [page:todo]</h3>
+		<h3>.clone() [page:Triangle]</h3>
 		<div>
 		<div>
-		todo
+		Return a new copy of this triangle.
 		</div>
 		</div>
 
 
-		<h3>.area() [page:todo]</h3>
+		<h3>.area() [page:Float]</h3>
 		<div>
 		<div>
-		todo
+		Return the area of the triangle.
 		</div>
 		</div>
 
 
-		<h3>.midpoint([page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.midpoint([page:Vector3 optionalTarget]) [page:Vector3]</h3>
 		<div>
 		<div>
-		optionalTarget -- todo
+		optionalTarget -- Optional [page:Vector3] target to set the result.
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Return the midpoint of the triangle. Optionally sets a target vector.
 		</div>
 		</div>
 
 
-		<h3>.equals([page:todo triangle]) [page:todo]</h3>
+		<h3>.equals([page:Triangle triangle]) [page:Boolean]</h3>
 		<div>
 		<div>
-		triangle -- todo
+		triangle -- [page:Triangle]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Checks to see if two triangles are equal (share the same vectors).
 		</div>
 		</div>
 
 
-		<h3>.plane([page:todo optionalTarget]) [page:todo]</h3>
+		<h3>.plane([page:Plane optionalTarget]) [page:Plane]</h3>
 		<div>
 		<div>
-		optionalTarget -- todo
+		optionalTarget -- Optional [page:Plane] target to set the result.
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Return a [page:Plane plane] based on the triangle. Optionally sets a target plane. 
 		</div>
 		</div>
 
 
-		<h3>.containsPoint([page:todo point]) [page:todo]</h3>
+		<h3>.containsPoint([page:Vector3 point]) [page:Boolean]</h3>
 		<div>
 		<div>
-		point -- todo
+		point -- [page:Vector3]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Checks to see if the passed vector is within the triangle.
 		</div>
 		</div>
 
 
-		<h3>.copy([page:todo triangle]) [page:todo]</h3>
+		<h3>.copy([page:Triangle triangle]) [page:Triangle]</h3>
 		<div>
 		<div>
-		triangle -- todo
+		triangle -- [page:Triangle]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Copies the values of the vertices of the passed triangle to this triangle.
 		</div>
 		</div>
 
 
 		<h2>Source</h2>
 		<h2>Source</h2>

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

@@ -159,12 +159,12 @@
 		Sets this vector to cross product of *a* and *b*.
 		Sets this vector to cross product of *a* and *b*.
 		</div>
 		</div>
 
 
-		<h3>.getPositionFromMatrix( [page:Matrix4 m] ) [page:Vector3 this]</h3>
+		<h3>.setFromMatrixPosition( [page:Matrix4 m] ) [page:Vector3 this]</h3>
 		<div>
 		<div>
 		Sets this vector extracting position from matrix transform.
 		Sets this vector extracting position from matrix transform.
 		</div>
 		</div>
 
 
-		<h3>.getScaleFromMatrix( [page:Matrix4 m] ) [page:Vector3 this]</h3>
+		<h3>.setFromMatrixScale( [page:Matrix4 m] ) [page:Vector3 this]</h3>
 		<div>
 		<div>
 		Sets this vector extracting scale from matrix transform.
 		Sets this vector extracting scale from matrix transform.
 		</div>
 		</div>
@@ -321,7 +321,7 @@
 		Returns the angle between this vector and vector v in radians.
 		Returns the angle between this vector and vector v in radians.
 		</div>
 		</div>
 
 
-		<h3>.getColumnFromMatrix([page:Integer index], [page:Matrix4 matrix]) [page:Vector3 this]</h3>
+		<h3>.setFromMatrixColumn([page:Integer index], [page:Matrix4 matrix]) [page:Vector3 this]</h3>
 		<div>
 		<div>
 		index -- 0, 1, 2, or 3 <br />
 		index -- 0, 1, 2, or 3 <br />
 		matrix -- [page:Matrix4]
 		matrix -- [page:Matrix4]

+ 6 - 1
docs/api/math/Vector4.html

@@ -210,7 +210,12 @@
 		value -- [page:Float]
 		value -- [page:Float]
 		</div>
 		</div>
 		<div>
 		<div>
-		todo
+		Sets the value of the vector component  x, y, or z by an index.<br/><br/>
+		
+		Index 0: x<br/>
+		Index 1: y<br/>
+		Index 2: z<br/>
+		Index 3: w<br/>
 		</div>
 		</div>
 		
 		
 		<h3>.fromArray([page:Array array]) [page:Vector4 this]</h3>
 		<h3>.fromArray([page:Array array]) [page:Vector4 this]</h3>

+ 1 - 3
docs/api/renderers/WebGLRenderer.html

@@ -23,13 +23,11 @@
 		<div>
 		<div>
 		canvas — A [page:Canvas] where the renderer draws its output.<br />
 		canvas — A [page:Canvas] where the renderer draws its output.<br />
 		precision — shader precision. Can be *"highp"*, *"mediump"* or *"lowp"*.<br />
 		precision — shader precision. Can be *"highp"*, *"mediump"* or *"lowp"*.<br />
-		alpha — [page:Boolean], default is *true*.<br />
+		alpha — [page:Boolean], default is *false*.<br />
 		premultipliedAlpha — [page:Boolean], default is *true*.<br />
 		premultipliedAlpha — [page:Boolean], default is *true*.<br />
 		antialias — [page:Boolean], default is *false*.<br />
 		antialias — [page:Boolean], default is *false*.<br />
 		stencil — [page:Boolean], default is *true*.<br />
 		stencil — [page:Boolean], default is *true*.<br />
 		preserveDrawingBuffer — [page:Boolean], default is *false*.<br />
 		preserveDrawingBuffer — [page:Boolean], default is *false*.<br />
-		clearColor — [page:Integer], default is *0x000000*.<br />
-		clearAlpha — [page:Float], default is *0*.<br />
 		maxLights — [page:Integer], default is *4*.<br />
 		maxLights — [page:Integer], default is *4*.<br />
 		</div>
 		</div>
 
 

+ 4 - 8
docs/api/renderers/WebGLShaders.html → docs/api/renderers/shaders/ShaderChunk.html

@@ -2,20 +2,16 @@
 <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>
 
 
-		<div class="desc">todo</div>
+		<div class="desc">Shader chunks for WebLG Shader library</div>
 
 
 
 
-		<h2>Constructor</h2>
-
-		<h3>[name]()</h3>
-
 
 
 		<h2>Properties</h2>
 		<h2>Properties</h2>
 
 

+ 27 - 0
docs/api/renderers/shaders/ShaderLib.html

@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<script src="../../../list.js"></script>
+		<script src="../../../page.js"></script>
+		<link type="text/css" rel="stylesheet" href="../../../page.css" />
+	</head>
+	<body>
+		<h1>[name]</h1>
+
+		<div class="desc">Webgl Shader Library for three.js</div>
+
+
+		<h2>Properties</h2>
+
+
+
+		<h2>Methods</h2>
+
+
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

+ 28 - 0
docs/api/renderers/shaders/UniformsLib.html

@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<script src="../../../list.js"></script>
+		<script src="../../../page.js"></script>
+		<link type="text/css" rel="stylesheet" href="../../../page.css" />
+	</head>
+	<body>
+		<h1>[name]</h1>
+
+		<div class="desc">Uniforms library for shared webgl shaders</div>
+
+
+
+		<h2>Properties</h2>
+
+
+
+		<h2>Methods</h2>
+
+
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

+ 26 - 0
docs/api/renderers/shaders/UniformsUtils.html

@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<script src="../../../list.js"></script>
+		<script src="../../../page.js"></script>
+		<link type="text/css" rel="stylesheet" href="../../../page.css" />
+	</head>
+	<body>
+		<h1>[name]</h1>
+
+		<div class="desc">Uniform Utilities. Support merging and cloning of uniform variables</div>
+
+		<h2>Properties</h2>
+
+
+
+		<h2>Methods</h2>
+
+
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

+ 9 - 2
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" ],
@@ -105,8 +106,7 @@ var list = {
 			[ "CanvasRenderer", "api/renderers/CanvasRenderer" ],
 			[ "CanvasRenderer", "api/renderers/CanvasRenderer" ],
 			[ "WebGLRenderer", "api/renderers/WebGLRenderer" ],
 			[ "WebGLRenderer", "api/renderers/WebGLRenderer" ],
 			[ "WebGLRenderTarget", "api/renderers/WebGLRenderTarget" ],
 			[ "WebGLRenderTarget", "api/renderers/WebGLRenderTarget" ],
-			[ "WebGLRenderTargetCube", "api/renderers/WebGLRenderTargetCube" ],
-			[ "WebGLShaders", "api/renderers/WebGLShaders" ]
+			[ "WebGLRenderTargetCube", "api/renderers/WebGLRenderTargetCube" ]
 		],
 		],
 
 
 		"Renderers / Renderables": [
 		"Renderers / Renderables": [
@@ -117,6 +117,13 @@ var list = {
 			[ "RenderableVertex", "api/renderers/renderables/RenderableVertex" ]
 			[ "RenderableVertex", "api/renderers/renderables/RenderableVertex" ]
 		],
 		],
 
 
+		"Renderers / Shaders": [
+			[ "ShaderChunk", "api/renderers/shaders/ShaderChunk" ],
+			[ "UniformsUtils", "api/renderers/shaders/UniformsUtils" ],
+			[ "UniformsLib", "api/renderers/shaders/UniformsLib" ],
+			[ "ShaderLib", "api/renderers/shaders/ShaderLib" ]
+		],
+
 		"Scenes": [
 		"Scenes": [
 			[ "Fog", "api/scenes/Fog" ],
 			[ "Fog", "api/scenes/Fog" ],
 			[ "FogExp2", "api/scenes/FogExp2" ],
 			[ "FogExp2", "api/scenes/FogExp2" ],

+ 4 - 3
editor/index.html

@@ -166,14 +166,15 @@
 
 
 				switch ( event.keyCode ) {
 				switch ( event.keyCode ) {
 
 
+					case 8: // prevent browser back 
+						event.preventDefault();
+						break;
 					case 46: // delete
 					case 46: // delete
-
 						editor.removeObject( editor.selected );
 						editor.removeObject( editor.selected );
 						editor.deselect();
 						editor.deselect();
-
 						break;
 						break;
 
 
-					}
+				}
 
 
 			}, false );
 			}, false );
 
 

+ 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 );
 
 
 					}
 					}

+ 5 - 2
examples/css3d_periodictable.html

@@ -247,8 +247,8 @@
 
 
 			function init() {
 			function init() {
 
 
-				camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 5000 );
-				camera.position.z = 1500;
+				camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 );
+				camera.position.z = 3000;
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
 
 
@@ -365,6 +365,8 @@
 
 
 				controls = new THREE.TrackballControls( camera, renderer.domElement );
 				controls = new THREE.TrackballControls( camera, renderer.domElement );
 				controls.rotateSpeed = 0.5;
 				controls.rotateSpeed = 0.5;
+				controls.minDistance = 500;
+				controls.maxDistance = 6000;
 				controls.addEventListener( 'change', render );
 				controls.addEventListener( 'change', render );
 
 
 				var button = document.getElementById( 'table' );
 				var button = document.getElementById( 'table' );
@@ -447,6 +449,7 @@
 				requestAnimationFrame( animate );
 				requestAnimationFrame( animate );
 
 
 				TWEEN.update();
 				TWEEN.update();
+
 				controls.update();
 				controls.update();
 
 
 			}
 			}

+ 5 - 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",
@@ -143,6 +144,7 @@
 				"webgl_geometry_terrain_raycast",
 				"webgl_geometry_terrain_raycast",
 				"webgl_geometry_tessellation",
 				"webgl_geometry_tessellation",
 				"webgl_geometry_text",
 				"webgl_geometry_text",
+				"webgl_gpgpu_birds",
 				"webgl_hdr",
 				"webgl_hdr",
 				"webgl_helpers",
 				"webgl_helpers",
 				"webgl_interactive_cubes",
 				"webgl_interactive_cubes",
@@ -217,6 +219,7 @@
 				"webgl_multiple_canvases_grid",
 				"webgl_multiple_canvases_grid",
 				"webgl_multiple_views",
 				"webgl_multiple_views",
 				"webgl_multiple_windows",
 				"webgl_multiple_windows",
+				"webgl_nearestneighbour",
 				"webgl_octree",
 				"webgl_octree",
 				"webgl_octree_raycasting",
 				"webgl_octree_raycasting",
 				"webgl_panorama_equirectangular",
 				"webgl_panorama_equirectangular",
@@ -235,6 +238,7 @@
 				"webgl_postprocessing_dof",
 				"webgl_postprocessing_dof",
 				"webgl_postprocessing_dof2",
 				"webgl_postprocessing_dof2",
 				"webgl_postprocessing_godrays",
 				"webgl_postprocessing_godrays",
+				"webgl_postprocessing_crossfade",
 				"webgl_rtt",
 				"webgl_rtt",
 				"webgl_sandbox",
 				"webgl_sandbox",
 				"webgl_shader",
 				"webgl_shader",
@@ -405,4 +409,4 @@
 		</script>
 		</script>
 
 
 	</body>
 	</body>
-</html>
+</html>

+ 2 - 2
examples/js/AudioObject.js

@@ -110,8 +110,8 @@ THREE.AudioObject = function ( url, volume, playbackRate, loop ) {
 		oldSoundPosition.copy( soundPosition );
 		oldSoundPosition.copy( soundPosition );
 		oldCameraPosition.copy( cameraPosition );
 		oldCameraPosition.copy( cameraPosition );
 
 
-		soundPosition.getPositionFromMatrix( this.matrixWorld );
-		cameraPosition.getPositionFromMatrix( camera.matrixWorld );
+		soundPosition.setFromMatrixPosition( this.matrixWorld );
+		cameraPosition.setFromMatrixPosition( camera.matrixWorld );
 
 
 		soundDelta.subVectors( soundPosition, oldSoundPosition );
 		soundDelta.subVectors( soundPosition, oldSoundPosition );
 		cameraDelta.subVectors( cameraPosition, oldCameraPosition );
 		cameraDelta.subVectors( cameraPosition, oldCameraPosition );

+ 2 - 2
examples/js/Mirror.js

@@ -180,8 +180,8 @@ THREE.Mirror.prototype.updateTextureMatrix = function () {
 	this.updateMatrixWorld();
 	this.updateMatrixWorld();
 	this.camera.updateMatrixWorld();
 	this.camera.updateMatrixWorld();
 
 
-	this.mirrorWorldPosition.getPositionFromMatrix( this.matrixWorld );
-	this.cameraWorldPosition.getPositionFromMatrix( this.camera.matrixWorld );
+	this.mirrorWorldPosition.setFromMatrixPosition( this.matrixWorld );
+	this.cameraWorldPosition.setFromMatrixPosition( this.camera.matrixWorld );
 
 
 	this.rotationMatrix.extractRotation( this.matrixWorld );
 	this.rotationMatrix.extractRotation( this.matrixWorld );
 
 

+ 1 - 1
examples/js/Octree.js

@@ -686,7 +686,7 @@
 				} else {
 				} else {
 					
 					
 					this.radius = this.object.boundRadius;
 					this.radius = this.object.boundRadius;
-					this.position.getPositionFromMatrix( this.object.matrixWorld );
+					this.position.setFromMatrixPosition( this.object.matrixWorld );
 					
 					
 				}
 				}
 				
 				

+ 236 - 0
examples/js/SimulatorRenderer.js

@@ -0,0 +1,236 @@
+/**
+ * @author zz85 https://github.com/zz85 / http://www.lab4games.net/zz85/blog
+ *
+ * Bird Simulation Render
+ *
+ * 	A simple scene rendering a quad of the following shaders
+ *	1. Pass-thru Shader,
+ *	2. Bird Position Update Shader,
+ *	3. Bird Velocity Update Shader
+ *
+ */
+
+function SimulatorRenderer(WIDTH, renderer) {
+
+	WIDTH = WIDTH || 4;
+	var camera = new THREE.Camera();
+	camera.position.z = 1;
+
+	// Init RTT stuff
+	gl = renderer.getContext();
+
+	if( !gl.getExtension( "OES_texture_float" )) {
+		alert( "No OES_texture_float support for float textures!" );
+		return;
+	}
+
+	if( gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS) == 0) {
+		alert( "No support for vertex shader textures!" );
+		return;
+	}
+
+	var scene = new THREE.Scene();
+
+	var uniforms = {
+		time: { type: "f", value: 1.0 },
+		resolution: { type: "v2", value: new THREE.Vector2( WIDTH, WIDTH ) },
+		texture: { type: "t", value: null }
+	};
+
+	var passThruShader = new THREE.ShaderMaterial( {
+		uniforms: uniforms,
+		vertexShader: document.getElementById( 'vertexShader' ).textContent,
+		fragmentShader: document.getElementById( 'fragmentShader' ).textContent
+	} );
+
+	var mesh = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), passThruShader );
+
+	var positionShader = new THREE.ShaderMaterial( {
+
+		uniforms: {
+			time: { type: "f", value: 1.0 },
+			delta: { type: "f", value: 0.0 },
+			resolution: { type: "v2", value: new THREE.Vector2( WIDTH, WIDTH ) },
+			texturePosition: { type: "t", value: null },
+			textureVelocity: { type: "t", value: null },
+		},
+		vertexShader: document.getElementById( 'vertexShader' ).textContent,
+		fragmentShader: document.getElementById( 'fragmentShaderPosition' ).textContent
+
+	} );
+
+	this.positionShader = positionShader;
+
+	var velocityShader = new THREE.ShaderMaterial( {
+
+		uniforms: {
+			time: { type: "f", value: 1.0 },
+			delta: { type: "f", value: 0.0 },
+			resolution: { type: "v2", value: new THREE.Vector2( WIDTH, WIDTH ) },
+			texturePosition: { type: "t", value: null },
+			textureVelocity: { type: "t", value: null },
+			testing: { type: "f", value: 1.0 },
+			seperationDistance: { type: "f", value: 1.0 },
+			alignmentDistance: { type: "f", value: 1.0 },
+			cohesionDistance: { type: "f", value: 1.0 },
+			freedomFactor: { type: "f", value: 1.0 },
+			predator: { type: "v3", value: new THREE.Vector3() }
+		},
+		defines: {
+			WIDTH: WIDTH.toFixed(2)
+		},
+		vertexShader: document.getElementById( 'vertexShader' ).textContent,
+		fragmentShader: document.getElementById( 'fragmentShaderVelocity' ).textContent
+
+	} );
+
+	this.velocityUniforms = velocityShader.uniforms;
+
+	scene.add( mesh );
+
+	var flipflop = true;
+	var rtPosition1, rtPosition2, rtVelocity1, rtVelocity2;
+
+	function init() {
+		var dtPosition = generateDataTexture();
+		var dtVelocity = generateVelocityTexture();
+
+		rtPosition1 = getRenderTarget();
+		rtPosition2 = rtPosition1.clone();
+		rtVelocity1 = rtPosition1.clone();
+		rtVelocity2 = rtPosition1.clone();
+
+		simulator.renderTexture(dtPosition, rtPosition1);
+		simulator.renderTexture(rtPosition1, rtPosition2);
+
+		simulator.renderTexture(dtVelocity, rtVelocity1);
+		simulator.renderTexture(rtVelocity1, rtVelocity2);
+
+		simulator.velocityUniforms.testing.value = 10;
+	}
+
+	this.init = init;
+
+	function getRenderTarget() {
+		var renderTarget = new THREE.WebGLRenderTarget(WIDTH, WIDTH, {
+			wrapS: THREE.RepeatWrapping,
+			wrapT: THREE.RepeatWrapping,
+			minFilter: THREE.NearestFilter,
+			magFilter: THREE.NearestFilter,
+			format: THREE.RGBAFormat,
+			type: THREE.FloatType,
+			stencilBuffer: false
+		});
+
+		return renderTarget;
+	}
+
+	// Takes a texture, and render out as another texture
+	this.renderTexture = function ( input, output ) {
+		mesh.material = passThruShader;
+		uniforms.texture.value = input;
+		renderer.render( scene, camera, output );
+	}
+
+
+	this.renderPosition = function(position, velocity, output, delta) {
+		mesh.material = positionShader;
+		positionShader.uniforms.texturePosition.value = position;
+		positionShader.uniforms.textureVelocity.value = velocity;
+		positionShader.uniforms.time.value = performance.now();
+		positionShader.uniforms.delta.value = delta;
+		renderer.render( scene, camera, output );
+		this.currentPosition = output;
+	}
+
+	this.renderVelocity = function(position, velocity, output, delta) {
+		mesh.material = velocityShader;
+		velocityShader.uniforms.texturePosition.value = position;
+		velocityShader.uniforms.textureVelocity.value = velocity;
+		velocityShader.uniforms.time.value = performance.now();
+		velocityShader.uniforms.delta.value = delta;
+		renderer.render( scene, camera, output );
+		this.currentVelocity = output;
+	}
+
+	this.simulate = function( delta ) {
+
+		if (flipflop) {
+
+			simulator.renderVelocity( rtPosition1, rtVelocity1, rtVelocity2, delta );
+			simulator.renderPosition( rtPosition1, rtVelocity2, rtPosition2, delta );
+
+		} else {
+
+			simulator.renderVelocity( rtPosition2, rtVelocity2, rtVelocity1, delta );
+			simulator.renderPosition( rtPosition2, rtVelocity1, rtPosition1, delta );
+
+		}
+
+		flipflop = !flipflop;
+
+	}
+
+	function generateDataTexture() {
+
+		var x, y, z;
+
+		var w = WIDTH, h = WIDTH;
+
+		var a = new Float32Array(PARTICLES * 4);
+
+		for (var k = 0; k < PARTICLES; k++) {
+
+			x = Math.random() * BOUNDS - BOUNDS_HALF;
+			y = Math.random() * BOUNDS - BOUNDS_HALF;
+			z = Math.random() * BOUNDS - BOUNDS_HALF;
+
+			a[ k*4 + 0 ] = x;
+			a[ k*4 + 1 ] = y;
+			a[ k*4 + 2 ] = z;
+			a[ k*4 + 3 ] = 1;
+
+		}
+
+		var texture = new THREE.DataTexture( a, WIDTH, WIDTH, THREE.RGBAFormat, THREE.FloatType );
+		texture.minFilter = THREE.NearestFilter;
+		texture.magFilter = THREE.NearestFilter;
+		texture.needsUpdate = true;
+		texture.flipY = false;
+
+		return texture;
+
+	}
+
+	function generateVelocityTexture() {
+
+		var x, y, z;
+
+		var w = WIDTH, h = WIDTH;
+
+		var a = new Float32Array(PARTICLES * 4);
+
+		for (var k = 0; k < PARTICLES; k++) {
+
+			x = Math.random() - 0.5;
+			y = Math.random() - 0.5;
+			z = Math.random() - 0.5;
+
+			a[ k*4 + 0 ] = x * 10;
+			a[ k*4 + 1 ] = y * 10;
+			a[ k*4 + 2 ] = z * 10;
+			a[ k*4 + 3 ] = 1;
+
+		}
+
+		var texture = new THREE.DataTexture( a, WIDTH, WIDTH, THREE.RGBAFormat, THREE.FloatType );
+		texture.minFilter = THREE.NearestFilter;
+		texture.magFilter = THREE.NearestFilter;
+		texture.needsUpdate = true;
+		texture.flipY = false;
+
+		return texture;
+
+	}
+
+}

+ 594 - 0
examples/js/TypedArrayUtils.js

@@ -0,0 +1,594 @@
+
+THREE.TypedArrayUtils = {};
+
+/**
+ * In-place quicksort for typed arrays (e.g. for Float32Array)
+ * provides fast sorting
+ * useful e.g. for a custom shader and/or BufferGeometry
+ *
+ * @author Roman Bolzern <[email protected]>, 2013
+ * @author I4DS http://www.fhnw.ch/i4ds, 2013
+ * @license MIT License <http://www.opensource.org/licenses/mit-license.php>
+ *
+ * Complexity: http://bigocheatsheet.com/ see Quicksort
+ *
+ * Example: 
+ * points: [x, y, z, x, y, z, x, y, z, ...]
+ * eleSize: 3 //because of (x, y, z)
+ * orderElement: 0 //order according to x
+ */
+
+THREE.TypedArrayUtils.quicksortIP = function ( arr, eleSize, orderElement ) {
+
+	var stack = [];
+	var sp = -1;
+	var left = 0;
+	var right = arr.length / eleSize - 1;
+	var tmp = 0.0, x = 0, y = 0;
+
+	var swapF = function ( a, b ) {
+
+		a *= eleSize; b *= eleSize;
+
+		for ( y = 0; y < eleSize; y ++ ) {
+
+			tmp = arr[ a + y ];
+			arr[ a + y ]=arr[ b + y ];
+			arr[ b + y ]=tmp;
+
+		}
+
+	};
+	
+	var i, j, swap = new Float32Array( eleSize ), temp = new Float32Array( eleSize );
+
+	while ( true ) {
+
+		if ( right - left <= 25 ) {
+
+			for ( j= left + 1; j <= right; j ++ ) {
+
+				for ( x = 0; x < eleSize; x ++ ) {
+			
+					swap[ x ] = arr[ j * eleSize + x ];
+
+				}
+				
+				i = j - 1;
+				
+				while ( i >= left && arr[ i * eleSize + orderElement ] > swap[orderElement ] ) {
+
+					for ( x = 0; x < eleSize; x ++ ) {
+
+						arr[ ( i + 1 ) * eleSize + x ] = arr[ i * eleSize + x ];
+
+					}
+
+					i --;
+
+				}
+
+				for ( x = 0; x < eleSize; x ++ ) {
+
+					arr[ ( i + 1 ) * eleSize + x ] = swap[ x ];
+
+				}
+
+			}
+			
+			if ( sp == -1 ) break;
+
+			right = stack[ sp -- ]; //?
+			left = stack[ sp -- ];
+
+		} else {
+
+			var median = ( left + right ) >> 1;
+
+			i = left + 1;
+			j = right;
+	
+			swapF( median, i );
+
+			if ( arr[ left * eleSize + orderElement ] > arr[ right * eleSize + orderElement ] ) {
+		
+				swapF( left, right );
+				
+			}
+
+			if ( arr[ i * eleSize + orderElement ] > arr[ right * eleSize + orderElement ] ) {
+		
+				swapF( i, right );
+		
+			}
+
+			if ( arr[ left * eleSize + orderElement ] > arr[ i * eleSize + orderElement ] ) {
+		
+				swapF( left, i );
+			
+			}
+
+			for ( x = 0; x < eleSize; x ++ ) {
+
+				temp[ x ] = arr[ i * eleSize + x ];
+
+			}
+			
+			while ( true ) {
+				
+				do i ++; while ( arr[ i * eleSize + orderElement ] < temp[ orderElement ] );
+				do j --; while ( arr[ j * eleSize + orderElement ] > temp[ orderElement ] );
+				
+				if ( j < i ) break;
+		
+				swapF( i, j );
+			
+			}
+
+			for ( x = 0; x < eleSize; x ++ ) {
+
+				arr[ ( left + 1 ) * eleSize + x ] = arr[ j * eleSize + x ];
+				arr[ j * eleSize + x ] = temp[ x ];
+
+			}
+
+			if ( right - i + 1 >= j - left ) {
+
+				stack[ ++ sp ] = i;
+				stack[ ++ sp ] = right;
+				right = j - 1;
+
+			} else {
+
+				stack[ ++ sp ] = left;
+				stack[ ++ sp ] = j - 1;
+				left = i;
+
+			}
+
+		}
+
+	}
+
+	return arr;
+
+};
+
+
+
+/**
+ * k-d Tree for typed arrays (e.g. for Float32Array), in-place
+ * provides fast nearest neighbour search
+ * useful e.g. for a custom shader and/or BufferGeometry, saves tons of memory
+ * has no insert and remove, only buildup and neares neighbour search
+ *
+ * Based on https://github.com/ubilabs/kd-tree-javascript by Ubilabs
+ *
+ * @author Roman Bolzern <[email protected]>, 2013
+ * @author I4DS http://www.fhnw.ch/i4ds, 2013
+ * @license MIT License <http://www.opensource.org/licenses/mit-license.php>
+ *
+ * Requires typed array quicksort
+ *
+ * Example: 
+ * points: [x, y, z, x, y, z, x, y, z, ...]
+ * metric: function(a, b){	return Math.pow(a[0] - b[0], 2) +  Math.pow(a[1] - b[1], 2) +  Math.pow(a[2] - b[2], 2); }  //Manhatten distance
+ * eleSize: 3 //because of (x, y, z)
+ *
+ * Further information (including mathematical properties)
+ * http://en.wikipedia.org/wiki/Binary_tree
+ * http://en.wikipedia.org/wiki/K-d_tree
+ *
+ * If you want to further minimize memory usage, remove Node.depth and replace in search algorithm with a traversal to root node (see comments at THREE.TypedArrayUtils.Kdtree.prototype.Node)
+ */
+
+ THREE.TypedArrayUtils.Kdtree = function ( points, metric, eleSize ) {
+
+	var self = this;
+	
+	var maxDepth = 0;
+	
+	var getPointSet = function ( points, pos ) {
+
+		return points.subarray( pos * eleSize, pos * eleSize + eleSize );
+
+	};
+		
+	function buildTree( points, depth, parent, pos ) {
+
+		var dim = depth % eleSize,
+			median,
+			node,
+			plength = points.length / eleSize;
+
+		if ( depth > maxDepth ) maxDepth = depth;
+		
+		if ( plength === 0 ) return null;
+		if ( plength === 1 ) {
+
+			return new self.Node( getPointSet( points, 0 ), depth, parent, pos );
+
+		}
+
+		THREE.TypedArrayUtils.quicksortIP( points, eleSize, dim );
+		
+		median = Math.floor( plength / 2 );
+		
+		node = new self.Node( getPointSet( points, median ) , depth, parent, median + pos );
+		node.left = buildTree( points.subarray( 0, median * eleSize), depth + 1, node, pos );
+		node.right = buildTree( points.subarray( ( median + 1 ) * eleSize, points.length ), depth + 1, node, pos + median + 1 );
+
+		return node;
+	
+	}
+
+	this.root = buildTree( points, 0, null, 0 );
+		
+	this.getMaxDepth = function () { return maxDepth; };
+	
+	this.nearest = function ( point, maxNodes , maxDistance ) {
+	
+		 /* point: array of size eleSize 
+			maxNodes: max amount of nodes to return 
+			maxDistance: maximum distance to point result nodes should have
+			condition (not implemented): function to test node before it's added to the result list, e.g. test for view frustum
+		*/
+
+		var i,
+			result,
+			bestNodes;
+
+		bestNodes = new THREE.TypedArrayUtils.Kdtree.BinaryHeap(
+
+			function ( e ) { return -e[ 1 ]; }
+
+		);
+
+		function nearestSearch( node ) {
+
+			var bestChild,
+				dimension = node.depth % eleSize,
+				ownDistance = metric(point, node.obj),
+				linearDistance = 0,
+				otherChild,
+				i,
+				linearPoint = [];
+
+			function saveNode( node, distance ) {
+
+				bestNodes.push( [ node, distance ] );
+
+				if ( bestNodes.size() > maxNodes ) {
+
+					bestNodes.pop();
+
+				}
+
+			}
+
+			for ( i = 0; i < eleSize; i += 1 ) {
+
+				if ( i === node.depth % eleSize ) {
+
+					linearPoint[ i ] = point[ i ];
+
+				} else {
+
+					linearPoint[ i ] = node.obj[ i ];
+
+				}
+
+			}
+
+			linearDistance = metric( linearPoint, node.obj );
+
+			// if it's a leaf
+
+			if ( node.right === null && node.left === null ) {
+
+				if ( bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[ 1 ] ) {
+
+					saveNode( node, ownDistance );
+
+				}
+
+				return;
+
+			}
+
+			if ( node.right === null ) {
+
+				bestChild = node.left;
+
+			} else if ( node.left === null ) {
+
+				bestChild = node.right;
+
+			} else {
+
+				if ( point[ dimension ] < node.obj[ dimension ] ) {
+
+					bestChild = node.left;
+
+				} else {
+
+					bestChild = node.right;
+
+				}
+
+			}
+
+			// recursive search
+
+			nearestSearch( bestChild );
+
+			if ( bestNodes.size() < maxNodes || ownDistance < bestNodes.peek()[ 1 ] ) {
+
+				saveNode( node, ownDistance );
+
+			}
+
+			// if there's still room or the current distance is nearer than the best distance
+
+			if ( bestNodes.size() < maxNodes || Math.abs(linearDistance) < bestNodes.peek()[ 1 ] ) {
+
+				if ( bestChild === node.left ) {
+
+					otherChild = node.right;
+
+				} else {
+
+					otherChild = node.left;
+
+				}
+
+				if ( otherChild !== null ) {
+
+					nearestSearch( otherChild );
+
+				}
+
+			}
+
+		}
+
+		if ( maxDistance ) {
+
+			for ( i = 0; i < maxNodes; i += 1 ) {
+
+				bestNodes.push( [ null, maxDistance ] );
+
+			}
+
+		}
+
+		nearestSearch( self.root );
+
+		result = [];
+
+		for ( i = 0; i < maxNodes; i += 1 ) {
+
+			if ( bestNodes.content[ i ][ 0 ] ) {
+
+				result.push( [ bestNodes.content[ i ][ 0 ], bestNodes.content[ i ][ 1 ] ] );
+
+			}
+
+		}
+		
+		return result;
+	
+	};
+	
+};
+
+/**
+ * If you need to free up additional memory and agree with an additional O( log n ) traversal time you can get rid of "depth" and "pos" in Node:
+ * Depth can be easily done by adding 1 for every parent (care: root node has depth 0, not 1)
+ * Pos is a bit tricky: Assuming the tree is balanced (which is the case when after we built it up), perform the following steps:
+ *   By traversing to the root store the path e.g. in a bit pattern (01001011, 0 is left, 1 is right)
+ *   From buildTree we know that "median = Math.floor( plength / 2 );", therefore for each bit...
+ *     0: amountOfNodesRelevantForUs = Math.floor( (pamountOfNodesRelevantForUs - 1) / 2 );
+ *     1: amountOfNodesRelevantForUs = Math.ceil( (pamountOfNodesRelevantForUs - 1) / 2 );
+ *        pos += Math.floor( (pamountOfNodesRelevantForUs - 1) / 2 );
+ *     when recursion done, we still need to add all left children of target node:
+ *        pos += Math.floor( (pamountOfNodesRelevantForUs - 1) / 2 );
+ *        and I think you need to +1 for the current position, not sure.. depends, try it out ^^
+ *
+ * I experienced that for 200'000 nodes you can get rid of 4 MB memory each, leading to 8 MB memory saved.
+ */
+THREE.TypedArrayUtils.Kdtree.prototype.Node = function ( obj, depth, parent, pos ) {
+
+	this.obj = obj;
+	this.left = null;
+	this.right = null;
+	this.parent = parent;
+	this.depth = depth;
+	this.pos = pos;
+
+}; 
+
+/**
+ * Binary heap implementation
+ * @author http://eloquentjavascript.net/appendix2.htm
+ */
+
+THREE.TypedArrayUtils.Kdtree.BinaryHeap = function ( scoreFunction ) {
+
+	this.content = [];
+	this.scoreFunction = scoreFunction;
+
+};
+
+THREE.TypedArrayUtils.Kdtree.BinaryHeap.prototype = {
+
+	push: function ( element ) {
+
+		// Add the new element to the end of the array.
+		this.content.push( element );
+
+		// Allow it to bubble up.
+		this.bubbleUp( this.content.length - 1 );
+
+	},
+
+	pop: function () {
+
+		// Store the first element so we can return it later.
+		var result = this.content[ 0 ];
+
+		// Get the element at the end of the array.
+		var end = this.content.pop();
+
+		// If there are any elements left, put the end element at the
+		// start, and let it sink down.
+		if ( this.content.length > 0 ) {
+
+			this.content[ 0 ] = end;
+			this.sinkDown( 0 );
+
+		}
+
+		return result;
+
+	},
+
+	peek: function () {
+
+		return this.content[ 0 ];
+
+	},
+
+	remove: function ( node ) {
+
+		var len = this.content.length;
+
+		// To remove a value, we must search through the array to find it.
+		for ( var i = 0; i < len; i ++ ) {
+
+			if ( this.content[ i ] == node ) {
+
+				// When it is found, the process seen in 'pop' is repeated
+				// to fill up the hole.
+				var end = this.content.pop();
+
+				if ( i != len - 1 ) {
+
+					this.content[ i ] = end;
+
+					if ( this.scoreFunction( end ) < this.scoreFunction( node ) ) {
+
+						this.bubbleUp( i );
+
+					} else {
+
+						this.sinkDown( i );
+
+					}
+
+				}
+
+				return;
+
+			}
+
+		}
+
+		throw new Error( "Node not found." );
+
+	},
+
+	size: function () {
+
+		return this.content.length;
+
+	},
+
+	bubbleUp: function ( n ) {
+
+		// Fetch the element that has to be moved.
+		var element = this.content[ n ];
+
+		// When at 0, an element can not go up any further.
+		while ( n > 0 ) {
+
+			// Compute the parent element's index, and fetch it.
+			var parentN = Math.floor( ( n + 1 ) / 2 ) - 1,
+				parent = this.content[ parentN ];
+
+			// Swap the elements if the parent is greater.
+			if ( this.scoreFunction( element ) < this.scoreFunction( parent ) ) {
+
+				this.content[ parentN ] = element;
+				this.content[ n ] = parent;
+
+				// Update 'n' to continue at the new position.
+				n = parentN;
+
+			} else {
+
+				// Found a parent that is less, no need to move it further.
+				break;
+
+			}
+
+		}
+
+	},
+
+	sinkDown: function ( n ) {
+
+		// Look up the target element and its score.
+		var length = this.content.length,
+			element = this.content[ n ],
+			elemScore = this.scoreFunction( element );
+
+		while ( true ) {
+
+			// Compute the indices of the child elements.
+			var child2N = ( n + 1 ) * 2, child1N = child2N - 1;
+
+			// This is used to store the new position of the element, if any.
+			var swap = null;
+
+			// If the first child exists (is inside the array)...
+			if ( child1N < length ) {
+
+				// Look it up and compute its score.
+				var child1 = this.content[ child1N ],
+					child1Score = this.scoreFunction( child1 );
+
+				// If the score is less than our element's, we need to swap.
+				if ( child1Score < elemScore ) swap = child1N;
+
+			}
+
+			// Do the same checks for the other child.
+			if ( child2N < length ) {
+
+				var child2 = this.content[ child2N ],
+					child2Score = this.scoreFunction( child2 );
+
+				if ( child2Score < ( swap === null ? elemScore : child1Score ) ) swap = child2N;
+
+			}
+
+			// If the element needs to be moved, swap it, and continue.
+			if ( swap !== null ) {
+
+				this.content[ n ] = this.content[ swap ];
+				this.content[ swap ] = element;
+				n = swap;
+
+			} else {
+
+				// Otherwise, we are done.
+				break;
+
+			}
+
+		}
+
+	}
+
+};

+ 95 - 71
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 ) {
@@ -83,6 +84,10 @@ THREE.TrackballControls = function ( object, domElement ) {
 		} else {
 		} else {
 
 
 			this.screen = this.domElement.getBoundingClientRect();
 			this.screen = this.domElement.getBoundingClientRect();
+			// adjustments come from similar code in the jquery offset() function
+			var d = this.domElement.ownerDocument.documentElement
+			this.screen.left += window.pageXOffset - d.clientLeft
+			this.screen.top += window.pageYOffset - d.clientTop
 
 
 		}
 		}
 
 
@@ -98,89 +103,101 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 
 	};
 	};
 
 
-	this.getMouseOnScreen = function ( clientX, clientY ) {
+	this.getMouseOnScreen = function ( pageX, pageY, optionalTarget ) {
 
 
-		return new THREE.Vector2(
-			( clientX - _this.screen.left ) / _this.screen.width,
-			( clientY - _this.screen.top ) / _this.screen.height
+		return ( optionalTarget || new THREE.Vector2() ).set(
+			( pageX - _this.screen.left ) / _this.screen.width,
+			( pageY - _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 objectUp = new THREE.Vector3();
 
 
-		var length = mouseOnBall.length();
 
 
-		if ( _this.noRoll ) {
+		return function ( pageX, pageY, projection ) {
 
 
-			if ( length < Math.SQRT1_2 ) {
+			var mouseOnBall = new THREE.Vector3(
+				( pageX - _this.screen.width * 0.5 - _this.screen.left ) / (_this.screen.width*.5),
+				( _this.screen.height * 0.5 + _this.screen.top - pageY ) / (_this.screen.height*.5),
+				0.0
+			);
 
 
-				mouseOnBall.z = Math.sqrt( 1.0 - length*length );
+			var length = mouseOnBall.length();
 
 
-			} else {
+			if ( _this.noRoll ) {
 
 
-				mouseOnBall.z = .5 / length;
-				
-			}
+				if ( length < Math.SQRT1_2 ) {
+
+					mouseOnBall.z = Math.sqrt( 1.0 - length*length );
 
 
-		} else if ( length > 1.0 ) {
+				} else {
+
+					mouseOnBall.z = .5 / length;
+					
+				}
 
 
-			mouseOnBall.normalize();
+			} else if ( length > 1.0 ) {
 
 
-		} else {
+				mouseOnBall.normalize();
 
 
-			mouseOnBall.z = Math.sqrt( 1.0 - length * length );
+			} 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 +231,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 +398,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.pageX, event.pageY, _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.pageX, event.pageY, _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.pageX, event.pageY, _panStart);
 			_panEnd.copy(_panStart)
 			_panEnd.copy(_panStart)
 
 
 		}
 		}
@@ -405,15 +429,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.pageX, event.pageY, _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.pageX, event.pageY, _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.pageX, event.pageY, _panEnd );
 
 
 		}
 		}
 
 
@@ -467,7 +491,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 +503,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 +525,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 +535,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 +552,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 +560,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;
 
 
 		}
 		}

+ 3 - 3
examples/js/controls/TransformControls.js

@@ -819,11 +819,11 @@ THREE.TransformControls = function ( camera, domElement ) {
 		if ( scope.object === undefined ) return;
 		if ( scope.object === undefined ) return;
 
 
 		scope.object.updateMatrixWorld();
 		scope.object.updateMatrixWorld();
-		worldPosition.getPositionFromMatrix( scope.object.matrixWorld );
+		worldPosition.setFromMatrixPosition( scope.object.matrixWorld );
 		worldRotation.setFromRotationMatrix( tempMatrix.extractRotation( scope.object.matrixWorld ) );
 		worldRotation.setFromRotationMatrix( tempMatrix.extractRotation( scope.object.matrixWorld ) );
 
 
 		camera.updateMatrixWorld();
 		camera.updateMatrixWorld();
-		camPosition.getPositionFromMatrix( camera.matrixWorld );
+		camPosition.setFromMatrixPosition( camera.matrixWorld );
 		camRotation.setFromRotationMatrix( tempMatrix.extractRotation( camera.matrixWorld ) );
 		camRotation.setFromRotationMatrix( tempMatrix.extractRotation( camera.matrixWorld ) );
 
 
 		scale = worldPosition.distanceTo( camPosition ) / 6 * scope.size;
 		scale = worldPosition.distanceTo( camPosition ) / 6 * scope.size;
@@ -900,7 +900,7 @@ THREE.TransformControls = function ( camera, domElement ) {
 				worldRotationMatrix.extractRotation( scope.object.matrixWorld );
 				worldRotationMatrix.extractRotation( scope.object.matrixWorld );
 
 
 				parentRotationMatrix.extractRotation( scope.object.parent.matrixWorld );
 				parentRotationMatrix.extractRotation( scope.object.parent.matrixWorld );
-				parentScale.getScaleFromMatrix( tempMatrix.getInverse( scope.object.parent.matrixWorld ) );
+				parentScale.setFromMatrixScale( tempMatrix.getInverse( scope.object.parent.matrixWorld ) );
 
 
 				offset.copy( planeIntersect.point );
 				offset.copy( planeIntersect.point );
 
 

+ 39 - 0
examples/js/crossfade/gui.js

@@ -0,0 +1,39 @@
+var transitionParams = {
+	"useTexture": true,
+	"transition": 0.5,
+	"transitionSpeed": 2.0,
+	"texture": 5,
+	"loopTexture": true,
+	"animateTransition": true,
+	"textureThreshold": 0.3
+};
+
+function initGUI() {
+	
+	var gui = new dat.GUI();
+
+	gui.add(transitionParams, "useTexture").onChange(function(value) {
+		
+		transition.useTexture(value);
+		
+	});
+	
+	gui.add(transitionParams, 'loopTexture');
+	
+	gui.add(transitionParams, 'texture', { Perlin: 0, Squares: 1, Cells: 2, Distort: 3, Gradient: 4, Radial: 5 } ).onChange(function(value) {
+		
+		transition.setTexture(value);
+		
+	}).listen();
+		
+	gui.add(transitionParams, "textureThreshold", 0, 1, 0.01).onChange(function(value) {
+		
+		transition.setTextureThreshold(value);
+		
+	});
+
+	gui.add(transitionParams, "animateTransition");
+	gui.add(transitionParams, "transition", 0, 1, 0.01).listen();
+	gui.add(transitionParams, "transitionSpeed", 0.5, 5, 0.01);
+	
+}

+ 108 - 0
examples/js/crossfade/scenes.js

@@ -0,0 +1,108 @@
+function generateGeometry(objectType, numObjects) {
+
+	var geometry = new THREE.Geometry();
+	
+	function applyVertexColors( g, c ) {
+
+		g.faces.forEach( function( f ) {
+
+			var n = ( f instanceof THREE.Face3 ) ? 3 : 4;
+
+			for( var j = 0; j < n; j ++ ) {
+
+				f.vertexColors[ j ] = c;
+
+			}
+
+		} );
+
+	}
+
+	for ( var i = 0; i < numObjects; i ++ ) {
+	
+		var position = new THREE.Vector3();
+
+		position.x = Math.random() * 10000 - 5000;
+		position.y = Math.random() * 6000 - 3000;
+		position.z = Math.random() * 8000 - 4000;
+
+		var rotation = new THREE.Euler();
+
+		rotation.x = Math.random() * 2 * Math.PI;
+		rotation.y = Math.random() * 2 * Math.PI;
+		rotation.z = Math.random() * 2 * Math.PI;
+
+		var scale = new THREE.Vector3();
+
+		var geom, color=new THREE.Color();
+
+		scale.x = Math.random() * 200 + 100;
+
+		if ( objectType == "cube" )
+		{
+			geom = new THREE.CubeGeometry( 1, 1, 1 );
+			scale.y = Math.random() * 200 + 100;
+			scale.z = Math.random() * 200 + 100;
+			color.setRGB( 0, 0, Math.random()+0.1 );
+		}
+		else if ( objectType == "sphere" )
+		{
+			geom = new THREE.IcosahedronGeometry( 1, 1 )
+			scale.y = scale.z = scale.x;
+			color.setRGB( Math.random()+0.1, 0, 0 );
+		}
+		
+		// give the geom's vertices a random color, to be displayed
+		applyVertexColors( geom, color );
+
+		var cube = new THREE.Mesh( geom );
+		cube.position.copy( position );
+		cube.rotation.copy( rotation );
+		cube.scale.copy( scale );
+
+		THREE.GeometryUtils.merge( geometry, cube );
+
+	}
+
+	return geometry;
+
+}
+
+function Scene ( type, numObjects, cameraZ, fov, rotationSpeed, clearColor ) {
+	
+	this.clearColor = clearColor;
+	
+	this.camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 10000 );
+	this.camera.position.z = cameraZ;
+	
+	// Setup scene
+	this.scene = new THREE.Scene();
+	this.scene.add( new THREE.AmbientLight( 0x555555 ) );
+
+	var light = new THREE.SpotLight( 0xffffff, 1.5 );
+	light.position.set( 0, 500, 2000 );
+	this.scene.add( light );
+
+	this.rotationSpeed = rotationSpeed;
+	defaultMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors	} );
+	this.mesh = new THREE.Mesh( generateGeometry( type, numObjects ), defaultMaterial );
+	this.scene.add( this.mesh );
+
+	renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false };
+	this.fbo = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, renderTargetParameters );
+	
+	this.render = function( delta, rtt ) {
+		
+		this.mesh.rotation.x += delta*this.rotationSpeed.x;
+		this.mesh.rotation.y += delta*this.rotationSpeed.y;
+		this.mesh.rotation.z += delta*this.rotationSpeed.z;
+		
+		renderer.setClearColor( this.clearColor, 1 );
+		
+		if (rtt)
+			renderer.render( this.scene, this.camera, this.fbo, true );
+		else
+			renderer.render( this.scene, this.camera );
+		
+	};
+}

+ 165 - 0
examples/js/crossfade/transition.js

@@ -0,0 +1,165 @@
+function Transition ( sceneA, sceneB ) {
+
+	this.scene = new THREE.Scene();
+	
+	this.cameraOrtho = new THREE.OrthographicCamera(window.innerWidth / -2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / -2, -10, 10);
+
+	this.textures = [];
+	for (var i=0;i<6;i++)
+		this.textures[i]=new THREE.ImageUtils.loadTexture('textures/transition/transition'+(i+1)+'.png');
+				
+	this.quadmaterial = new THREE.ShaderMaterial({
+
+		uniforms: {
+
+			tDiffuse1: {
+				type: "t",
+				value: null
+			},
+			tDiffuse2: {
+				type: "t",
+				value: null
+			},
+			mixRatio: {
+				type: "f",
+				value: 0.0
+			},
+			threshold: {
+				type: "f",
+				value: 0.1
+			},
+			useTexture: {
+				type: "i",
+				value: 1,
+			},
+			tMixTexture: {
+				type: "t",
+				value: this.textures[0]
+			}
+		},
+		vertexShader: [
+
+			"varying vec2 vUv;",
+
+			"void main() {",
+
+			"vUv = vec2( uv.x, uv.y );",
+			"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+
+			"}"
+
+		].join("\n"),
+		fragmentShader: [
+
+			"uniform float mixRatio;",
+
+			"uniform sampler2D tDiffuse1;",
+			"uniform sampler2D tDiffuse2;",
+			"uniform sampler2D tMixTexture;",
+			
+			"uniform int useTexture;",
+			"uniform float threshold;",
+
+			"varying vec2 vUv;",
+
+			"void main() {",
+
+			"vec4 texel1 = texture2D( tDiffuse1, vUv );",
+			"vec4 texel2 = texture2D( tDiffuse2, vUv );",
+			
+			"if (useTexture==1) {",
+				
+				"vec4 transitionTexel = texture2D( tMixTexture, vUv );",
+				"float r = mixRatio * (1.0 + threshold * 2.0) - threshold;",
+				"float mixf=clamp((transitionTexel.r - r)*(1.0/threshold), 0.0, 1.0);",
+				
+				"gl_FragColor = mix( texel1, texel2, mixf );",
+			"} else {",
+				
+				"gl_FragColor = mix( texel2, texel1, mixRatio );",
+				
+			"}",
+		"}"
+
+		].join("\n")
+
+	});		
+
+	quadgeometry = new THREE.PlaneGeometry(window.innerWidth, window.innerHeight);
+	
+	this.quad = new THREE.Mesh(quadgeometry, this.quadmaterial);
+	this.scene.add(this.quad);
+
+	// Link both scenes and their FBOs
+	this.sceneA = sceneA;
+	this.sceneB = sceneB;
+
+	this.quadmaterial.uniforms.tDiffuse1.value = sceneA.fbo;
+	this.quadmaterial.uniforms.tDiffuse2.value = sceneB.fbo;
+
+	this.needChange = false;
+	
+	this.setTextureThreshold = function ( value ) {
+	
+		this.quadmaterial.uniforms.threshold.value=value;
+
+	}
+	
+	this.useTexture = function ( value ) {
+	
+		this.quadmaterial.uniforms.useTexture.value = value?1:0;
+
+	}
+	
+	this.setTexture = function ( i ) {
+		
+		this.quadmaterial.uniforms.tMixTexture.value = this.textures[i];
+		
+	}
+	
+	this.render = function( delta ) {
+		
+		// Transition animation
+		if (transitionParams.animateTransition)
+		{
+			var t=(1+Math.sin(transitionParams.transitionSpeed*clock.getElapsedTime()/Math.PI))/2;
+			transitionParams.transition=THREE.Math.smoothstep(t,0.3,0.7);
+			
+			// Change the current alpha texture after each transition
+			if (transitionParams.loopTexture && (transitionParams.transition==0 || transitionParams.transition==1))
+			{
+				if (this.needChange)
+				{
+					transitionParams.texture=(transitionParams.texture+1)%this.textures.length;
+					this.quadmaterial.uniforms.tMixTexture.value = this.textures[transitionParams.texture];
+					this.needChange=false;
+				}
+			}	
+			else
+				this.needChange=true;
+				
+		}
+		
+		this.quadmaterial.uniforms.mixRatio.value = transitionParams.transition;
+
+		// Prevent render both scenes when it's not necessary
+		if (transitionParams.transition==0) {
+			
+			this.sceneB.render( delta, false );
+		
+		} else if (transitionParams.transition==1) {
+		
+			this.sceneA.render( delta, false );
+			
+		} else {
+			
+			// When 0<transition<1 render transition between two scenes
+			
+			this.sceneA.render( delta, true );
+			this.sceneB.render( delta, true );
+			renderer.render( this.scene, this.cameraOrtho, null, true );
+
+		}
+
+	}
+}

+ 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';
 
 

+ 1 - 1
examples/js/loaders/ctm/ctm.js

@@ -630,7 +630,7 @@ CTM.Stream.prototype.readString = function(){
 
 
   this.offset += len;
   this.offset += len;
 
 
-  return this.data.subarray(this.offset - len, len);
+  return String.fromCharCode.apply(null,this.data.subarray(this.offset - len, this.offset));
 };
 };
 
 
 CTM.Stream.prototype.readArrayInt32 = function(array){
 CTM.Stream.prototype.readArrayInt32 = function(array){

+ 96 - 0
examples/js/postprocessing/BokehPass.js

@@ -0,0 +1,96 @@
+/**
+ * Depth-of-field post-process with bokeh shader
+ */
+
+
+THREE.BokehPass = function ( scene, camera, params ) {
+
+	this.scene = scene;
+	this.camera = camera;
+
+	var focus = ( params.focus !== undefined ) ? params.focus : 1.0;
+	var aspect = ( params.aspect !== undefined ) ? params.aspect : camera.aspect;
+	var aperture = ( params.aperture !== undefined ) ? params.aperture : 0.025;
+	var maxblur = ( params.maxblur !== undefined ) ? params.maxblur : 1.0;
+
+	// render targets
+
+	var width = params.width || window.innerWidth || 1;
+	var height = params.height || window.innerHeight || 1;
+
+	this.renderTargetColor = new THREE.WebGLRenderTarget( width, height, {
+		minFilter: THREE.LinearFilter,
+		magFilter: THREE.LinearFilter,
+		format: THREE.RGBFormat
+	} );
+
+	this.renderTargetDepth = this.renderTargetColor.clone();
+
+	// depth material
+
+	this.materialDepth = new THREE.MeshDepthMaterial();
+
+	// bokeh material
+
+	if ( THREE.BokehShader === undefined ) {
+		console.error( "THREE.BokehPass relies on THREE.BokehShader" );
+	}
+	
+	var bokehShader = THREE.BokehShader;
+	var bokehUniforms = THREE.UniformsUtils.clone( bokehShader.uniforms );
+
+	bokehUniforms[ "tDepth" ].value = this.renderTargetDepth;
+
+	bokehUniforms[ "focus" ].value = focus;
+	bokehUniforms[ "aspect" ].value = aspect;
+	bokehUniforms[ "aperture" ].value = aperture;
+	bokehUniforms[ "maxblur" ].value = maxblur;
+
+	this.materialBokeh = new THREE.ShaderMaterial({
+		uniforms: bokehUniforms,
+		vertexShader: bokehShader.vertexShader,
+		fragmentShader: bokehShader.fragmentShader
+	});
+
+	this.uniforms = bokehUniforms;
+	this.enabled = true;
+	this.needsSwap = false;
+	this.renderToScreen = false;
+	this.clear = false;
+
+};
+
+THREE.BokehPass.prototype = {
+
+	render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) {
+
+		var composer = THREE.EffectComposer;
+
+		composer.quad.material = this.materialBokeh;
+
+		// Render depth into texture
+
+		this.scene.overrideMaterial = this.materialDepth;
+
+		renderer.render( this.scene, this.camera, this.renderTargetDepth, true );
+
+		// Render bokeh composite
+
+		this.uniforms[ "tColor" ].value = readBuffer;
+
+		if ( this.renderToScreen ) {
+
+			renderer.render( composer.scene, composer.camera );
+
+		} else {
+
+			renderer.render( composer.scene, composer.camera, writeBuffer, this.clear );
+
+		}
+
+		this.scene.overrideMaterial = null;
+
+	}
+
+};
+

+ 1 - 1
examples/js/renderers/CSS2DRenderer.js

@@ -64,7 +64,7 @@ THREE.CSS2DRenderer = function () {
 
 
 		if ( object instanceof THREE.CSS2DObject ) {
 		if ( object instanceof THREE.CSS2DObject ) {
 
 
-			vector.getPositionFromMatrix( object.matrixWorld );
+			vector.setFromMatrixPosition( object.matrixWorld );
 			vector.applyProjection( viewProjectionMatrix );
 			vector.applyProjection( viewProjectionMatrix );
 
 
 			var element = object.element;
 			var element = object.element;

+ 2 - 2
examples/js/renderers/SVGRenderer.js

@@ -222,7 +222,7 @@ THREE.SVGRenderer = function () {
 
 
 			if ( light instanceof THREE.DirectionalLight ) {
 			if ( light instanceof THREE.DirectionalLight ) {
 
 
-				var lightPosition = _vector3.getPositionFromMatrix( light.matrixWorld ).normalize();
+				var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ).normalize();
 
 
 				var amount = normal.dot( lightPosition );
 				var amount = normal.dot( lightPosition );
 
 
@@ -236,7 +236,7 @@ THREE.SVGRenderer = function () {
 
 
 			} else if ( light instanceof THREE.PointLight ) {
 			} else if ( light instanceof THREE.PointLight ) {
 
 
-				var lightPosition = _vector3.getPositionFromMatrix( light.matrixWorld );
+				var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld );
 
 
 				var amount = normal.dot( _vector3.subVectors( lightPosition, position ).normalize() );
 				var amount = normal.dot( _vector3.subVectors( lightPosition, position ).normalize() );
 
 

+ 9 - 9
examples/js/renderers/WebGLDeferredRenderer.js

@@ -333,12 +333,12 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 			lightProxy.scale.set( 1, 1, 1 ).multiplyScalar( distance );
 			lightProxy.scale.set( 1, 1, 1 ).multiplyScalar( distance );
 			uniforms[ "lightRadius" ].value = distance;
 			uniforms[ "lightRadius" ].value = distance;
 
 
-			positionVS.getPositionFromMatrix( light.matrixWorld );
+			positionVS.setFromMatrixPosition( light.matrixWorld );
 			positionVS.applyMatrix4( currentCamera.matrixWorldInverse );
 			positionVS.applyMatrix4( currentCamera.matrixWorldInverse );
 
 
 			uniforms[ "lightPositionVS" ].value.copy( positionVS );
 			uniforms[ "lightPositionVS" ].value.copy( positionVS );
 
 
-			lightProxy.position.getPositionFromMatrix( light.matrixWorld );
+			lightProxy.position.setFromMatrixPosition( light.matrixWorld );
 
 
 		} else {
 		} else {
 
 
@@ -425,11 +425,11 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 		var viewMatrix = currentCamera.matrixWorldInverse;
 		var viewMatrix = currentCamera.matrixWorldInverse;
 		var modelMatrix = light.matrixWorld;
 		var modelMatrix = light.matrixWorld;
 
 
-		positionVS.getPositionFromMatrix( modelMatrix );
+		positionVS.setFromMatrixPosition( modelMatrix );
 		positionVS.applyMatrix4( viewMatrix );
 		positionVS.applyMatrix4( viewMatrix );
 
 
-		directionVS.getPositionFromMatrix( modelMatrix );
-		tempVS.getPositionFromMatrix( light.target.matrixWorld );
+		directionVS.setFromMatrixPosition( modelMatrix );
+		tempVS.setFromMatrixPosition( light.target.matrixWorld );
 		directionVS.sub( tempVS );
 		directionVS.sub( tempVS );
 		directionVS.normalize();
 		directionVS.normalize();
 		directionVS.transformDirection( viewMatrix );
 		directionVS.transformDirection( viewMatrix );
@@ -499,8 +499,8 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 		var light = lightProxy.userData.originalLight;
 		var light = lightProxy.userData.originalLight;
 		var uniforms = lightProxy.material.uniforms;
 		var uniforms = lightProxy.material.uniforms;
 
 
-		directionVS.getPositionFromMatrix( light.matrixWorld );
-		tempVS.getPositionFromMatrix( light.target.matrixWorld );
+		directionVS.setFromMatrixPosition( light.matrixWorld );
+		tempVS.setFromMatrixPosition( light.target.matrixWorld );
 		directionVS.sub( tempVS );
 		directionVS.sub( tempVS );
 		directionVS.normalize();
 		directionVS.normalize();
 		directionVS.transformDirection( currentCamera.matrixWorldInverse );
 		directionVS.transformDirection( currentCamera.matrixWorldInverse );
@@ -566,7 +566,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 		var light = lightProxy.userData.originalLight;
 		var light = lightProxy.userData.originalLight;
 		var uniforms = lightProxy.material.uniforms;
 		var uniforms = lightProxy.material.uniforms;
 
 
-		directionVS.getPositionFromMatrix( light.matrixWorld );
+		directionVS.setFromMatrixPosition( light.matrixWorld );
 		directionVS.normalize();
 		directionVS.normalize();
 		directionVS.transformDirection( currentCamera.matrixWorldInverse );
 		directionVS.transformDirection( currentCamera.matrixWorldInverse );
 
 
@@ -635,7 +635,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 		var modelMatrix = light.matrixWorld;
 		var modelMatrix = light.matrixWorld;
 		var viewMatrix = currentCamera.matrixWorldInverse;
 		var viewMatrix = currentCamera.matrixWorldInverse;
 
 
-		positionVS.getPositionFromMatrix( modelMatrix );
+		positionVS.setFromMatrixPosition( modelMatrix );
 		positionVS.applyMatrix4( viewMatrix );
 		positionVS.applyMatrix4( viewMatrix );
 
 
 		uniforms[ "lightPositionVS" ].value.copy( positionVS );
 		uniforms[ "lightPositionVS" ].value.copy( positionVS );

+ 1 - 1
examples/js/renderers/WebGLRenderer3.js

@@ -438,7 +438,7 @@ THREE.WebGLRenderer3 = function ( parameters ) {
 
 
 			} else {
 			} else {
 
 
-				vector3.getPositionFromMatrix( object.matrixWorld );
+				vector3.setFromMatrixPosition( object.matrixWorld );
 				vector3.applyProjection( cameraViewProjectionMatrix );
 				vector3.applyProjection( cameraViewProjectionMatrix );
 
 
 				object.z = vector3.z;
 				object.z = vector3.z;

BIN
examples/textures/transition/transition1.png


BIN
examples/textures/transition/transition2.png


BIN
examples/textures/transition/transition3.png


BIN
examples/textures/transition/transition4.png


BIN
examples/textures/transition/transition5.png


BIN
examples/textures/transition/transition6.png


+ 538 - 0
examples/webgl_geometry_extrude_shapes2.html

@@ -0,0 +1,538 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<title>three.js webgl - geometry - extrude shapes from geodata</title>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+<style>
+body {
+	font-family: Monospace;
+	background-color: #f0f0f0;
+	margin: 0px;
+	overflow: hidden;
+}
+</style>
+</head>
+
+<body>
+<canvas id="debug" style="position:absolute; left:100px"></canvas>
+
+
+
+<script>
+'use strict';
+</script>
+
+
+
+<script type="text/javascript" src="../build/three.min.js"></script>
+<script src="js/libs/stats.min.js"></script>
+
+
+
+<script>
+// From d3-threeD.js
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function d3threeD(exports) {
+
+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;
+
+exports.transformSVGPath =
+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 $d3g = {};
+d3threeD($d3g);
+</script>
+
+
+
+<script>
+/// Part from g0v/twgeojson
+/// Graphic Engine and Geo Data Init Functions
+
+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 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 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;
+};
+</script>
+
+
+
+<script>
+	/// Events from extrude shapes example
+
+	function onWindowResize() {
+
+		windowHalfX = window.innerWidth / 2;
+		windowHalfY = window.innerHeight / 2;
+
+		camera.aspect = window.innerWidth / window.innerHeight;
+		camera.updateProjectionMatrix();
+
+		renderer.setSize( window.innerWidth, window.innerHeight );
+	};
+
+	function onDocumentMouseDown( event ) {
+
+		event.preventDefault();
+
+		document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+		document.addEventListener( 'mouseup', onDocumentMouseUp, false );
+		document.addEventListener( 'mouseout', onDocumentMouseOut, false );
+
+		mouseXOnMouseDown = event.clientX - windowHalfX;
+		targetRotationOnMouseDown = targetRotation;
+	};
+
+	function onDocumentMouseMove( event ) {
+
+		mouseX = event.clientX - windowHalfX;
+
+		targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
+	};
+
+	function onDocumentMouseUp( event ) {
+
+		document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
+		document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
+		document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
+	};
+
+	function onDocumentMouseOut( event ) {
+
+		document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
+		document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
+		document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
+	};
+
+	function onDocumentTouchStart( event ) {
+
+		if ( event.touches.length == 1 ) {
+
+			event.preventDefault();
+
+			mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
+			targetRotationOnMouseDown = targetRotation;
+		}
+	};
+
+	function onDocumentTouchMove( event ) {
+
+		if ( event.touches.length == 1 ) {
+
+			event.preventDefault();
+
+			mouseX = event.touches[ 0 ].pageX - windowHalfX;
+			targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
+		}
+	};
+
+	function animate() {
+
+		/// compatibility : http://caniuse.com/requestanimationframe
+		requestAnimationFrame( animate );
+
+		render();
+		stats.update();
+	};
+
+	function render() {
+
+		group.rotation.y += ( targetRotation - group.rotation.y ) * 0.05;
+		renderer.render( scene, camera );
+	};
+</script>
+
+
+
+<script>
+	/// Main
+
+	var renderer, stats;
+	var scene, camera, group;
+
+	var targetRotation = 0;
+	var targetRotationOnMouseDown = 0;
+
+	var mouseX = 0;
+	var mouseXOnMouseDown = 0;
+
+	var windowHalfX = window.innerWidth / 2;
+	var windowHalfY = window.innerHeight / 2;
+
+	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 );
+
+	init3d();
+
+	container.appendChild( renderer.domElement );
+
+	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>
+
+
+
+</body>
+</html>

+ 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;

+ 806 - 0
examples/webgl_gpgpu_birds.html

@@ -0,0 +1,806 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - gpgpu - flocking</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				background-color: #ffffff;
+				margin: 0px;
+				overflow: hidden;
+				font-family:Monospace;
+				font-size:13px;
+				text-align:center;
+				text-align:center;
+				cursor: pointer;
+			}
+
+			a {
+				color:#0078ff;
+			}
+
+			#info {
+				color: #000;
+				position: absolute;
+				top: 10px;
+				width: 100%;
+			}
+
+		</style>
+	</head>
+	<body>
+
+		<div id="info">
+			<a href="http://threejs.org" target="_blank">three.js</a> - <span id="birds"></span> webgl gpgpu birds<br/>
+			Select <span id="options"></span> birds<br/>
+			Move mouse to disturb birds.
+			
+		</div>
+
+		<script src="../build/three.min.js"></script>
+		<script src="js/Detector.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+		<script src="js/libs/dat.gui.min.js"></script>
+
+		<script src="js/SimulatorRenderer.js"></script>
+
+		<!--
+		TODO: If you're reading this, you may wish to improve this example by
+			- Replacing the custom BirdGeometry with a BufferGeometry?
+			- Create a better shading for the birds?
+			- Refactoring the SimulationRenderer to a more generic TextureRenderer / making the GPGPU workflow easier?
+
+		-->
+
+
+
+		<!-- pass through vertex shader -->
+		<script id="vertexShader" type="x-shader/x-vertex">
+
+			void main()	{
+
+				gl_Position = vec4( position, 1.0 );
+
+			}
+
+		</script>
+
+		<!-- pass through fragment shader -->
+		<script id="fragmentShader" type="x-shader/x-fragment">
+
+			uniform vec2 resolution;
+			uniform float time;
+			uniform sampler2D texture;
+
+			void main()	{
+
+				vec2 uv = gl_FragCoord.xy / resolution.xy;
+
+				vec3 color = texture2D( texture, uv ).xyz;
+
+				gl_FragColor=vec4(color, 1.0);
+
+			}
+
+		</script>
+		<!-- end pass through shaders -->
+
+		<!-- shader for bird's position -->
+		<script id="fragmentShaderPosition" type="x-shader/x-fragment">
+
+			uniform vec2 resolution;
+			uniform float time;
+			uniform float delta;
+			uniform sampler2D textureVelocity;
+			uniform sampler2D texturePosition;
+
+			void main()	{
+
+				vec2 uv = gl_FragCoord.xy / resolution.xy;
+				vec4 tmpPos = texture2D( texturePosition, uv );
+				vec3 position = tmpPos.xyz;
+				vec3 velocity = texture2D( textureVelocity, uv ).xyz;
+
+				float phase = tmpPos.w;
+
+				phase = mod( ( phase + delta +
+					length( velocity.xz ) * delta * 3. +
+					max( velocity.y, 0.0 ) * delta * 6. ), 62.83 );
+
+				gl_FragColor = vec4( position + velocity * delta * 15. , phase );
+
+			}
+
+		</script>
+
+		<!-- shader for bird's velocity -->
+		<script id="fragmentShaderVelocity" type="x-shader/x-fragment">
+
+			uniform vec2 resolution;
+			uniform float time;
+			uniform float testing;
+			uniform float delta; // about 0.016
+			uniform float seperationDistance; // 20
+			uniform float alignmentDistance; // 40
+			uniform float cohesionDistance; // 
+			uniform float freedomFactor;
+			uniform vec3 predator;
+
+
+			uniform sampler2D textureVelocity;
+			uniform sampler2D texturePosition;
+
+			const float width = WIDTH;
+			const float height = WIDTH;
+
+			const float PI = 3.141592653589793;
+			const float PI_2 = PI * 2.0;
+			// const float VISION = PI * 0.55;
+
+			float zoneRadius = 40.0;
+			float zoneRadiusSquared = zoneRadius * zoneRadius;
+
+			float separationThresh = 0.45;
+			float alignmentThresh = 0.65;
+
+			const float UPPER_BOUNDS = 400.0;
+			const float LOWER_BOUNDS = -UPPER_BOUNDS;
+
+			const float SPEED_LIMIT = 9.0;
+
+			float rand(vec2 co){
+			    return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
+			}
+
+			void main()	{
+
+				zoneRadius = seperationDistance + alignmentDistance + cohesionDistance;
+				separationThresh = seperationDistance / zoneRadius;
+				alignmentThresh = ( seperationDistance + alignmentDistance ) / zoneRadius;
+				zoneRadiusSquared = zoneRadius * zoneRadius;
+
+
+				vec2 uv = gl_FragCoord.xy / resolution.xy;
+				vec3 birdPosition, birdVelocity;
+
+				vec3 selfPosition = texture2D( texturePosition, uv ).xyz;
+				vec3 selfVelocity = texture2D( textureVelocity, uv ).xyz;
+
+				float dist;
+				vec3 dir; // direction
+				float distSquared;
+
+				float seperationSquared = seperationDistance * seperationDistance;
+				float cohesionSquared = cohesionDistance * cohesionDistance;
+
+				float f;
+				float percent;
+
+				vec3 velocity = selfVelocity;
+
+				float limit = SPEED_LIMIT;
+
+				dir = predator * UPPER_BOUNDS - selfPosition;
+				dir.z = 0.;
+				// dir.z *= 0.6;
+				dist = length( dir );
+				distSquared = dist * dist;
+
+				float preyRadius = 150.0;
+				float preyRadiusSq = preyRadius * preyRadius;
+
+				
+				// move birds away from predator
+				if (dist < preyRadius) {
+
+					f = ( distSquared / preyRadiusSq - 1.0 ) * delta * 100.;
+					velocity += normalize( dir ) * f;
+					limit += 5.0;
+				}
+
+
+				// if (testing == 0.0) {}
+				// if ( rand( uv + time ) < freedomFactor ) {}
+
+
+				// Attract flocks to the center
+				vec3 central = vec3( 0., 0., 0. );
+				dir = selfPosition - central;
+				dist = length( dir );
+				dir.y *= 2.5;
+				velocity -= normalize( dir ) * delta * 5.;
+
+				for (float y=0.0;y<height;y++) {
+					for (float x=0.0;x<width;x++) {
+
+						if (
+							x == gl_FragCoord.x && y == gl_FragCoord.y) continue;
+
+						birdPosition = texture2D( texturePosition,
+							vec2( x / resolution.x,  y / resolution.y ) ).xyz;
+
+						dir = birdPosition - selfPosition;
+						dist = length(dir);
+						distSquared = dist * dist;
+
+						if ( dist > 0.0 && distSquared < zoneRadiusSquared ) {
+
+							percent = distSquared / zoneRadiusSquared;
+
+							if ( percent < separationThresh ) { // low
+
+								// Separation - Move apart for comfort
+								f = (separationThresh / percent - 1.0) * delta;
+								velocity -= normalize(dir) * f;
+
+							} else if ( percent < alignmentThresh ) { // high
+
+								// Alignment - fly the same direction
+								float threshDelta = alignmentThresh - separationThresh;
+								float adjustedPercent = ( percent - separationThresh ) / threshDelta;
+
+								birdVelocity = texture2D( textureVelocity, vec2(x/resolution.x, y/resolution.y) ).xyz;
+								
+								f = ( 0.5 - cos( adjustedPercent * PI_2 ) * 0.5 + 0.5 ) * delta;
+								velocity += normalize(birdVelocity) * f;
+
+							} else {
+
+								// Attraction / Cohesion - move closer
+								float threshDelta = 1.0 - alignmentThresh;
+								float adjustedPercent = ( percent - alignmentThresh ) / threshDelta;
+
+								 f = ( 0.5 - ( cos( adjustedPercent * PI_2 ) * -0.5 + 0.5 ) ) * delta;
+
+								 velocity += normalize(dir) * f;
+
+							}
+
+						}
+
+					}
+
+				}
+
+				
+
+				// this make tends to fly around than down or up
+				// if (velocity.y > 0.) velocity.y *= (1. - 0.2 * delta);
+
+				// Speed Limits
+				if ( length( velocity ) > limit ) {
+					velocity = normalize( velocity ) * limit;
+				}
+
+				gl_FragColor = vec4( velocity, 1.0 );
+
+			}
+
+		</script>
+
+		<script type="x-shader/x-vertex" id="birdVS">
+
+			attribute vec2 reference;
+			attribute float birdVertex;
+
+			attribute vec3 birdColor;
+			
+			uniform sampler2D texturePosition;
+			uniform sampler2D textureVelocity;
+
+			varying vec3 vNormal;
+			varying vec2 vUv;
+			varying vec4 vColor;
+			varying float z;
+
+			uniform float time;
+
+			void main() {
+
+				vNormal = normal;
+
+				vec4 tmpPos = texture2D( texturePosition, reference );
+				vec3 pos = tmpPos.xyz;
+				vec3 velocity = normalize(texture2D( textureVelocity, reference ).xyz);
+
+				vec3 newPosition = position;
+
+				if ( birdVertex == 4.0 || birdVertex == 7.0 ) {
+					// flap wings
+					newPosition.y = sin( tmpPos.w ) * 5.;
+				}
+
+				newPosition = mat3( modelMatrix ) * newPosition;
+
+
+				velocity.z *= -1.;
+				float xz = length( velocity.xz );
+				float xyz = 1.;
+				float x = sqrt( 1. - velocity.y * velocity.y );
+				
+				float cosry = velocity.x / xz;
+				float sinry = velocity.z / xz;
+
+				float cosrz = x / xyz;
+				float sinrz = velocity.y / xyz;
+
+				mat3 maty =  mat3(
+					cosry, 0, -sinry,
+					0    , 1, 0     ,
+					sinry, 0, cosry
+
+				);
+
+				mat3 matz =  mat3(
+					cosrz , sinrz, 0,
+					-sinrz, cosrz, 0,
+					0     , 0    , 1
+				);
+
+				newPosition =  maty * matz * newPosition;
+				newPosition += pos;
+
+				z = newPosition.z;
+				
+				vColor = vec4( birdColor, 1.0 );
+				gl_Position = projectionMatrix *  viewMatrix  * vec4( newPosition, 1.0 );
+			}
+
+		</script>
+
+		<!-- bird geometry shader -->
+		<script type="x-shader/x-fragment" id="birdFS">
+
+			varying vec3 vNormal;
+			varying vec2 vUv;
+			varying vec4 vColor;
+			varying float z;
+
+			uniform vec3 color;
+
+			void main() {
+				// Fake colors for now
+				float z2 = 0.2 + ( 1000. - z ) / 1000. * vColor.x;
+				gl_FragColor = vec4( z2, z2, z2, 1. );
+
+				// vec3 light = vec3( 0.0, 1.0, 1.0 );
+				// light = normalize( light );
+				// float dProd = dot( vNormal, light ) ; //* 0.5 + 0.5;
+				// vec4 tcolor = vColor;
+				// vec4 gray = vec4( vec3( tcolor.r * 0.3 + tcolor.g * 0.59 + tcolor.b * 0.11 ), 1.0 );
+
+				// gl_FragColor =  gray * dProd;
+				// gl_FragColor =  vec4( dProd  * tcolor );
+
+			}
+
+		</script>
+
+
+		<script>
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var hash = document.location.hash.substr( 1 );
+			if (hash) hash = parseInt(hash, 0);
+
+			/* TEXTURE WIDTH FOR SIMULATION */
+			var WIDTH = hash || 32; 
+
+			var BIRDS = 1024;
+
+			// Custom Geometry
+			THREE.BirdGeometry = function () {
+
+				THREE.Geometry.call( this );
+
+				BIRDS = WIDTH * WIDTH;
+
+				var verts = this.vertices;
+				var faces = this.faces;
+				var uvs = this.faceVertexUvs[ 0 ];
+
+				var fi = 0;
+
+				for (var f = 0; f<BIRDS; f++ ) {
+					verts.push(
+						new THREE.Vector3(0, -0, -20),
+						new THREE.Vector3(0, 4, -20),
+						new THREE.Vector3(0, 0, 30)
+					);
+
+					faces.push(new THREE.Face3(
+						fi++,
+						fi++,
+						fi++
+					));
+
+					uvs.push([
+						new THREE.Vector2(0, 0),
+						new THREE.Vector2(0, 1),
+						new THREE.Vector2(1, 1)
+					]);
+
+					var wingsSpan = 20;
+
+					verts.push(
+						new THREE.Vector3(0, 0, -15),
+						new THREE.Vector3(-wingsSpan, 0, 0),
+						new THREE.Vector3(0, 0, 15)
+					);
+
+					verts.push(
+						new THREE.Vector3(0, 0, 15),
+						new THREE.Vector3(wingsSpan, 0, 0),
+						new THREE.Vector3(0, 0, -15)
+					);
+
+					faces.push(new THREE.Face3(
+						fi++,
+						fi++,
+						fi++
+					));
+
+					faces.push(new THREE.Face3(
+						fi++,
+						fi++,
+						fi++
+					));
+
+					uvs.push([
+						new THREE.Vector2(0, 0),
+						new THREE.Vector2(0, 1),
+						new THREE.Vector2(1, 1)
+					]);
+
+					uvs.push([
+						new THREE.Vector2(0, 0),
+						new THREE.Vector2(0, 1),
+						new THREE.Vector2(1, 1)
+					]);
+
+				}
+
+				this.applyMatrix( new THREE.Matrix4().makeScale( 0.2, 0.2, 0.2 ) );
+
+				this.computeCentroids();
+				this.computeFaceNormals();
+				this.computeVertexNormals();
+
+			}
+
+
+			THREE.BirdGeometry.prototype = Object.create( THREE.Geometry.prototype );
+
+
+			var container, stats;
+			var camera, scene, renderer, geometry, i, h, color;
+			var mouseX = 0, mouseY = 0;
+
+			var windowHalfX = window.innerWidth / 2;
+			var windowHalfY = window.innerHeight / 2;
+			
+			var HEIGHT = WIDTH;
+			var PARTICLES = WIDTH * WIDTH;
+			var BOUNDS = 800, BOUNDS_HALF = BOUNDS / 2;
+
+			document.getElementById('birds').innerText = PARTICLES;
+
+			function change(n) {
+				location.hash = n;
+				location.reload();
+				return false;
+			}
+
+
+			var options = '';
+			for (i=1; i<7; i++) {
+				var j = Math.pow(2, i);
+				options += '<a href="#" onclick="return change(' + j + ')">' + (j * j) + '</a> ';
+			}
+			document.getElementById('options').innerHTML = options;
+
+			var debug;
+			var data, texture;
+
+			var spline = new THREE.SplineCurve3();
+
+
+			var timer = 0;
+			var paused = false;
+
+			var last = performance.now();
+			var delta, now, t = 0;
+
+
+			var simulator;
+
+			init();
+			animate();
+			onMouseDown();
+
+			function init() {
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 3000 );
+				camera.position.z = 350;
+
+				scene = new THREE.Scene();
+
+				scene.fog = new THREE.Fog( 0xffffff, 100, 1000 );
+
+				renderer = new THREE.WebGLRenderer();
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				container.appendChild( renderer.domElement );
+
+				renderer.setClearColor( scene.fog.color, 1 );
+				renderer.autoClear = true;
+
+				////////
+				simulator = new SimulatorRenderer(WIDTH, renderer);
+
+				simulator.init();
+
+				/////////
+
+
+		
+				plane = new THREE.PlaneGeometry( BOUNDS, BOUNDS, 1, 1 );
+				// new THREE.CubeGeometry( BOUNDS, BOUNDS, BOUNDS),
+
+				cube = new THREE.Mesh(
+					plane,
+					new THREE.MeshBasicMaterial( {color: 0xdddddd, wireframe: true, depthWrite: false} )
+				);
+
+				cube.rotation.x = -Math.PI / 2;
+				cube.position.y = -400;
+				// scene.add(cube);
+
+
+
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				container.appendChild( stats.domElement );
+
+				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+				// document.addEventListener( 'mousedown', onMouseDown, false );
+				document.addEventListener( 'mouseup', onMouseUp, false );
+				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
+				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
+
+				//
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+
+
+				var gui = new dat.GUI();
+
+
+				var effectController = {
+					seperation: 20.0,
+					alignment: 20.0,
+					cohesion: 20.0,
+					freedom: 0.75
+				};
+
+				var valuesChanger = function() {
+
+					simulator.velocityUniforms.seperationDistance.value = effectController.seperation;
+					simulator.velocityUniforms.alignmentDistance.value = effectController.alignment;
+					simulator.velocityUniforms.cohesionDistance.value = effectController.cohesion;
+					simulator.velocityUniforms.freedomFactor.value = effectController.freedom;
+
+				};
+
+				valuesChanger();
+
+
+				gui.add( effectController, "seperation", 0.0, 100.0, 1.0 ).onChange( valuesChanger );
+				gui.add( effectController, "alignment", 0.0, 100, 0.001 ).onChange( valuesChanger );
+				gui.add( effectController, "cohesion", 0.0, 100, 0.025 ).onChange( valuesChanger );
+				// gui.add( effectController, "freedom", 0.0, 1.0, 0.025 ).onChange( valuesChanger );
+				gui.close();
+
+				initBirds();
+
+
+				// var ambient = new THREE.AmbientLight( 0x444444 );
+				// scene.add( ambient );
+
+				// light = new THREE.DirectionalLight( 0xffffff );
+				// light.position.set( 1, 1, 1 );
+				// scene.add( light );
+
+
+				// light = new THREE.DirectionalLight( 0xffffff );
+				// light.position.set( -1, -1, -1 );
+				// scene.add( light );
+				
+
+
+			}
+
+
+			function initBirds() {
+				var geometry = new THREE.BirdGeometry( );
+
+
+				// For Vertex Shaders
+				birdAttributes = {
+					index: { type: 'i', value: [] },
+					birdColor: {	type: 'c', value: [] },
+					reference: { type: 'v2', value: [] },
+					birdVertex: { type: 'f', value: [] },
+				};
+
+				// For Vertex and Fragment
+				birdUniforms = {
+
+					color:     { type: "c", value: new THREE.Color( 0xff2200 ) },
+					texturePosition:     { type: "t", value: null },
+					textureVelocity:     { type: "t", value: null },
+					time: { type: "f", value: 1.0 },
+					delta: { type: "f", value: 0.0 },
+
+				};
+
+				// ShaderMaterial
+				var shaderMaterial = new THREE.ShaderMaterial( {
+
+					uniforms: 		birdUniforms,
+					attributes:     birdAttributes,
+					vertexShader:   document.getElementById( 'birdVS' ).textContent,
+					fragmentShader: document.getElementById( 'birdFS' ).textContent,
+					side: THREE.DoubleSide,
+					// wireframe: true
+
+				});
+
+				// geometry.dynamic = false;
+
+				var vertices = geometry.vertices;
+				var birdColors = birdAttributes.birdColor.value;
+				var references = birdAttributes.reference.value;
+				var birdVertex = birdAttributes.birdVertex.value;
+
+				for( var v = 0; v < vertices.length; v++ ) {
+
+					var i = ~~(v / 3);
+					var x = (i % WIDTH) / WIDTH;
+					var y = ~~(i / WIDTH) / WIDTH;
+
+					birdColors[ v ] = new THREE.Color(
+						0x444444 +
+						~~(v / 9) / BIRDS * 0x666666
+					);
+					references[ v ] = new THREE.Vector2( x, y );
+					birdVertex[ v ] = v % 9;
+
+				}
+
+
+				// var 
+				birdMesh = new THREE.Mesh( geometry, shaderMaterial );
+				birdMesh.rotation.y = Math.PI / 2;
+				birdMesh.sortObjects = false;
+
+				birdMesh.matrixAutoUpdate = false;
+				birdMesh.updateMatrix();
+
+				scene.add(birdMesh);
+
+			}
+
+			function onWindowResize() {
+
+				windowHalfX = window.innerWidth / 2;
+				windowHalfY = window.innerHeight / 2;
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function onDocumentMouseMove( event ) {
+
+				mouseX = event.clientX - windowHalfX;
+				mouseY = event.clientY - windowHalfY;
+
+			}
+
+			function onDocumentTouchStart( event ) {
+
+				if ( event.touches.length === 1 ) {
+
+					event.preventDefault();
+
+					mouseX = event.touches[ 0 ].pageX - windowHalfX;
+					mouseY = event.touches[ 0 ].pageY - windowHalfY;
+
+				}
+
+			}
+
+			function onDocumentTouchMove( event ) {
+
+				if ( event.touches.length === 1 ) {
+
+					event.preventDefault();
+
+					mouseX = event.touches[ 0 ].pageX - windowHalfX;
+					mouseY = event.touches[ 0 ].pageY - windowHalfY;
+
+				}
+
+			}
+
+			//
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				render();
+				stats.update();
+
+			}
+
+			function render() {
+				now = performance.now()
+				delta = (now - last) / 1000;
+
+				if (delta > 1) delta = 1; // safety cap on large deltas
+				last = now;
+
+				birdUniforms.time.value = now;
+				birdUniforms.delta.value = delta;
+
+				// if ( paused ) {
+				// 	camera.position.x += ( mouseX * 2 - camera.position.x ) * 0.05;
+				// 	camera.position.y += ( - mouseY * 2 - camera.position.y ) * 0.05;
+
+				// 	camera.lookAt( scene.position );
+				// 	delta = 0.0001;
+				// }
+
+				if (!paused) {
+					simulator.simulate( delta );
+
+					birdUniforms.texturePosition.value = simulator.currentPosition;
+					birdUniforms.textureVelocity.value = simulator.currentVelocity;
+				}
+
+
+				simulator.velocityUniforms.predator.value.set( mouseX / windowHalfX, -mouseY / windowHalfY, 0 );
+
+
+				mouseX = 10000;
+				mouseY = 10000;
+
+				renderer.render( scene, camera );
+
+			}
+
+			function onMouseDown() {
+				// simulator.velocityUniforms.testing.value = 0;
+			}
+
+			function onMouseUp() {
+				// simulator.velocityUniforms.testing.value = 1;
+			}
+
+
+
+
+		</script>
+	</body>
+</html>

+ 4 - 1
examples/webgl_loader_collada_skinning.html

@@ -39,7 +39,10 @@
 
 
 		<script src="../build/three.min.js"></script>
 		<script src="../build/three.min.js"></script>
 		<script src="./js/loaders/ColladaLoader.js"></script>
 		<script src="./js/loaders/ColladaLoader.js"></script>
-
+		<script src="../src/extras/animation/Animation.js"></script>
+		<script src="../src/extras/animation/AnimationHandler.js"></script>
+		<script src="../src/extras/animation/AnimationMorphTarget.js"></script>
+		<script src="../src/extras/animation/KeyFrameAnimation.js"></script>
 		<script src="js/Detector.js"></script>
 		<script src="js/Detector.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 
 

+ 247 - 0
examples/webgl_nearestneighbour.html

@@ -0,0 +1,247 @@
+<html>
+	<head>
+		<meta charset="utf-8">
+		<title>three.js webgl - nearest neighbour</title>
+		<style>
+			html, body {
+				width: 100%;
+				height: 100%;
+			}
+
+			body {
+				background-color: #ffffff;
+				margin: 0;
+				overflow: hidden;
+				font-family: arial;
+			}
+
+			#info {
+				text-align: center;
+				padding: 5px;
+				position: absolute;
+				width: 100%;
+				color: white;
+			}
+		</style>
+	</head>
+	<body>
+		
+		<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> webgl - typed arrays - nearest neighbour for 500,000 sprites</div>
+		
+		<script src="../build/three.min.js"></script>
+		<script src="js/TypedArrayUtils.js"></script>
+		<script src="js/controls/FirstPersonControls.js"></script>
+		<script type="x-shader/x-vertex" id="vertexshader">
+			
+			//uniform float zoom;
+		
+			attribute float alpha;
+
+			varying float vAlpha;
+
+			void main() {
+			
+				vAlpha = 1.0 - alpha;
+				
+				vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
+
+				gl_PointSize = 4.0 * ( 300.0 / length( mvPosition.xyz ) );
+
+				gl_Position = projectionMatrix * mvPosition;
+
+			}
+
+		</script>
+
+		<script type="x-shader/x-fragment" id="fragmentshader">
+
+			uniform sampler2D tex1;
+
+			varying float vAlpha;
+
+			void main() {
+
+				gl_FragColor = texture2D(tex1, gl_PointCoord);
+				gl_FragColor.r = (1.0 - gl_FragColor.r) * vAlpha + gl_FragColor.r;
+
+			}
+
+		</script>
+		<script>		
+		
+			var camera, scene, renderer;
+			var geometry, material, mesh;
+			var controls;
+
+			var objects = [];
+
+			var amountOfParticles = 500000, maxDistance = Math.pow(120, 2);
+			var positions, alphas, particles, _particleGeom
+
+			var clock = new THREE.Clock();
+
+			var blocker = document.getElementById( 'blocker' );
+			var instructions = document.getElementById( 'instructions' );
+			
+			
+			function init() {
+
+			    camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000000);
+
+				scene = new THREE.Scene();
+
+				controls = new THREE.FirstPersonControls( camera );
+				controls.movementSpeed = 100;
+				controls.lookSpeed = 0.1;
+
+				var materials = [
+
+					new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'textures/cube/skybox/px.jpg' ), overdraw: true } ), // right
+					new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'textures/cube/skybox/nx.jpg' ), overdraw: true } ), // left
+					new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'textures/cube/skybox/py.jpg' ), overdraw: true } ), // top
+					new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'textures/cube/skybox/ny.jpg' ), overdraw: true } ), // bottom
+					new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'textures/cube/skybox/pz.jpg' ), overdraw: true } ), // back
+					new THREE.MeshBasicMaterial( { map: THREE.ImageUtils.loadTexture( 'textures/cube/skybox/nz.jpg' ), overdraw: true } )  // front
+
+				];
+
+				mesh = new THREE.Mesh( new THREE.CubeGeometry( 10000, 10000, 10000, 7, 7, 7 ), new THREE.MeshFaceMaterial( materials ) );
+				mesh.scale.x = - 1;
+				scene.add(mesh);
+				
+				//
+
+				renderer = new THREE.WebGLRenderer(); // Detector.webgl? new THREE.WebGLRenderer(): new THREE.CanvasRenderer()
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+				document.body.appendChild( renderer.domElement );
+
+				// create the custom shader
+				var imagePreviewTexture = THREE.ImageUtils.loadTexture( 'textures/crate.gif');
+				imagePreviewTexture.minFilter = THREE.LinearMipMapLinearFilter;
+				imagePreviewTexture.magFilter = THREE.LinearFilter;
+				
+				pointShaderMaterial = new THREE.ShaderMaterial( {
+					uniforms: {
+						tex1: { type: "t", value: imagePreviewTexture },
+						zoom: { type: 'f', value: 9.0 },
+					},
+					attributes: {
+						alpha: { type: 'f', value: null },
+					},
+					vertexShader:   document.getElementById( 'vertexshader' ).textContent,
+					fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
+					transparent: true
+				});
+				
+				
+				//create particles with buffer geometry
+				var distanceFunction = function(a, b){
+					return Math.pow(a[0] - b[0], 2) +  Math.pow(a[1] - b[1], 2) +  Math.pow(a[2] - b[2], 2);
+				};
+				
+				_particleGeom = new THREE.BufferGeometry();
+				_particleGeom.dynamic = false;
+				_particleGeom.attributes = {
+
+					position: {
+						itemSize: 3,
+						array: new Float32Array( amountOfParticles * 3 )
+					},
+					
+					alpha: {
+						itemSize: 1,
+						array: new Float32Array( amountOfParticles ),
+						dynamic: true
+					}
+
+				};
+				positions = _particleGeom.attributes.position.array;
+				alphas = _particleGeom.attributes.alpha.array;
+				
+				particles = new THREE.ParticleSystem( _particleGeom, pointShaderMaterial );
+				particles.dynamic = true;
+				
+				for (var x = 0; x < amountOfParticles; x++) {
+					positions[ x * 3 + 0 ] = Math.random() * 1000;
+					positions[ x * 3 + 1 ] = Math.random() * 1000;
+					positions[ x * 3 + 2 ] = Math.random() * 1000;
+					alphas[x] = 1.0;
+				}
+				
+				
+				var measureStart = new Date().getTime();
+				
+				// creating the kdtree takes a lot of time to execute, in turn the nearest neighbour search will be much faster
+				kdtree = new THREE.TypedArrayUtils.Kdtree( positions, distanceFunction, 3 );
+				
+				console.log('TIME building kdtree', new Date().getTime() - measureStart);
+				
+				// display particles after the kd-tree was generated and the sorting of the positions-array is done
+				scene.add(particles);
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+				controls.handleResize();
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				//
+				displayNearest(camera.position);
+
+				controls.update( clock.getDelta() )
+
+				renderer.render( scene, camera );
+
+			}
+			
+			function displayNearest(position) {
+				
+				// take the nearest 200 around him. distance^2 'cause we use the manhattan distance and no square is applied in the distance function
+				var imagePositionsInRange = kdtree.nearest([position.x, position.y, position.z], 100, maxDistance);
+								
+				// We combine the nearest neighbour with a view frustum. Doesn't make sense if we change the sprites not in our view... well maybe it does. Whatever you want.
+				var _frustum = new THREE.Frustum();
+				var _projScreenMatrix = new THREE.Matrix4();
+				camera.matrixWorldInverse.getInverse( camera.matrixWorld );
+
+				_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
+				_frustum.setFromMatrix( _projScreenMatrix );
+				
+				for ( i = 0, il = imagePositionsInRange.length; i < il; i ++ ) {
+					var object = imagePositionsInRange[i];
+					var objectPoint = new THREE.Vector3(0,0,0);
+					objectPoint.x = object[0].obj[0];
+					objectPoint.y = object[0].obj[1];
+					objectPoint.z = object[0].obj[2];
+					
+					if (_frustum.containsPoint(objectPoint)){
+					
+						var objectIndex = object[0].pos;
+						
+						// set the alpha according to distance
+						alphas[ objectIndex ] = 1.0 / maxDistance * object[1];
+						// update the attribute
+						_particleGeom.attributes.alpha.needsUpdate = true;
+					}
+				}
+			}
+			
+			
+			init();
+			animate();
+		</script>
+	</body>
+</html>

+ 99 - 0
examples/webgl_postprocessing_crossfade.html

@@ -0,0 +1,99 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - scenes transition</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				font-family: Monospace;
+				background-color: #f0f0f0;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			.info {
+				position: absolute;
+				background-color: black;
+				opacity: 0.8;
+				color: white;
+				text-align: center;
+				top: 0px;
+				width: 100%;
+			}
+
+			.info a {
+				color: #00ffff;
+			}
+		</style>
+	</head>
+	<body>
+
+		<div class="info">
+			<a href="http://threejs.org" target="_blank">three.js</a> webgl scene transitions - by <a href="https://twitter.com/fernandojsg">fernandojsg</a> - <a href="https://github.com/kile/three.js-demos">github</a>
+		</div>
+
+		<div id="container"></div>
+
+		<script src="../build/three.min.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+		<script src="js/libs/dat.gui.min.js"></script>
+		<script src="js/crossfade/scenes.js"></script>
+		<script src="js/crossfade/gui.js"></script>
+		<script src="js/crossfade/transition.js"></script>
+		
+		<script>
+
+			var container, stats;
+			var renderer;
+			var transition;
+			
+			var clock = new THREE.Clock();
+
+			init();
+			animate();
+			
+			function init() {
+
+				initGUI();
+				
+				container = document.getElementById( "container" );
+
+				renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false } );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.sortObjects = false;
+
+				container.appendChild( renderer.domElement );
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				container.appendChild( stats.domElement );
+
+				sceneA = new Scene( "cube", 5000, 1200, 120, new THREE.Vector3(0,-0.4,0), 0xffffff );
+				sceneB = new Scene( "sphere", 500, 2000, 50, new THREE.Vector3(0,0.2,0.1), 0x000000 );
+				
+				transition = new Transition(sceneA,sceneB);
+				
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				render();
+				stats.update();
+
+			}
+			
+			function render() {
+				
+				transition.render( clock.getDelta() );
+				
+			}
+
+		</script>
+
+	</body>
+	
+</html>

+ 42 - 44
examples/webgl_postprocessing_dof.html

@@ -35,8 +35,15 @@
 	<body>
 	<body>
 		<script src="../build/three.min.js"></script>
 		<script src="../build/three.min.js"></script>
 
 
+		<script src="js/shaders/CopyShader.js"></script>
 		<script src="js/shaders/BokehShader.js"></script>
 		<script src="js/shaders/BokehShader.js"></script>
 
 
+		<script src="js/postprocessing/EffectComposer.js"></script>
+		<script src="js/postprocessing/RenderPass.js"></script>
+		<script src="js/postprocessing/ShaderPass.js"></script>
+		<script src="js/postprocessing/MaskPass.js"></script>
+		<script src="js/postprocessing/BokehPass.js"></script>
+
 		<script src="js/Detector.js"></script>
 		<script src="js/Detector.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 
 
@@ -64,6 +71,7 @@
 			var windowHalfX = window.innerWidth / 2;
 			var windowHalfX = window.innerWidth / 2;
 			var windowHalfY = window.innerHeight / 2;
 			var windowHalfY = window.innerHeight / 2;
 
 
+			var width = window.innerWidth;
 			var height = window.innerHeight - 300;
 			var height = window.innerHeight - 300;
 
 
 			var postprocessing = { enabled  : true };
 			var postprocessing = { enabled  : true };
@@ -76,13 +84,13 @@
 				container = document.createElement( 'div' );
 				container = document.createElement( 'div' );
 				document.body.appendChild( container );
 				document.body.appendChild( container );
 
 
-				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / height, 1, 3000 );
+				camera = new THREE.PerspectiveCamera( 70, width / height, 1, 3000 );
 				camera.position.z = 200;
 				camera.position.z = 200;
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
 
 
 				renderer = new THREE.WebGLRenderer( { antialias: false } );
 				renderer = new THREE.WebGLRenderer( { antialias: false } );
-				renderer.setSize( window.innerWidth, height );
+				renderer.setSize( width, height );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
 
 
 				renderer.sortObjects = false;
 				renderer.sortObjects = false;
@@ -177,6 +185,8 @@
 				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
 				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
 				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
 				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
 
 
+				window.addEventListener( 'resize', onWindowResize, false );
+
 				var effectController  = {
 				var effectController  = {
 
 
 					focus: 		1.0,
 					focus: 		1.0,
@@ -187,9 +197,9 @@
 
 
 				var matChanger = function( ) {
 				var matChanger = function( ) {
 
 
-					postprocessing.bokeh_uniforms[ "focus" ].value = effectController.focus;
-					postprocessing.bokeh_uniforms[ "aperture" ].value = effectController.aperture;
-					postprocessing.bokeh_uniforms[ "maxblur" ].value = effectController.maxblur;
+					postprocessing.bokeh.uniforms[ "focus" ].value = effectController.focus;
+					postprocessing.bokeh.uniforms[ "aperture" ].value = effectController.aperture;
+					postprocessing.bokeh.uniforms[ "maxblur" ].value = effectController.maxblur;
 
 
 				};
 				};
 
 
@@ -233,39 +243,43 @@
 
 
 			}
 			}
 
 
-			function initPostprocessing() {
+			function onWindowResize() {
 
 
-				postprocessing.scene = new THREE.Scene();
+				windowHalfX = window.innerWidth / 2;
+				windowHalfY = window.innerHeight / 2;
 
 
-				postprocessing.camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2,  window.innerHeight / 2, window.innerHeight / - 2, -10000, 10000 );
-				postprocessing.camera.position.z = 100;
+				width = window.innerWidth;
+				height = window.innerHeight - 300;
 
 
-				postprocessing.scene.add( postprocessing.camera );
+				camera.aspect = width / height;
+				camera.updateProjectionMatrix();
 
 
-				var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat };
-				postprocessing.rtTextureDepth = new THREE.WebGLRenderTarget( window.innerWidth, height, pars );
-				postprocessing.rtTextureColor = new THREE.WebGLRenderTarget( window.innerWidth, height, pars );
+				renderer.setSize( width, height );
+				postprocessing.composer.setSize( width, height );
+
+			}
 
 
-				var bokeh_shader = THREE.BokehShader;
+			function initPostprocessing() {
+				var renderPass = new THREE.RenderPass( scene, camera );
 
 
-				postprocessing.bokeh_uniforms = THREE.UniformsUtils.clone( bokeh_shader.uniforms );
+				var bokehPass = new THREE.BokehPass( scene, camera, {
+					focus: 		1.0,
+					aperture:	0.025,
+					maxblur:	1.0,
 
 
-				postprocessing.bokeh_uniforms[ "tColor" ].value = postprocessing.rtTextureColor;
-				postprocessing.bokeh_uniforms[ "tDepth" ].value = postprocessing.rtTextureDepth;
-				postprocessing.bokeh_uniforms[ "focus" ].value = 1.1;
-				postprocessing.bokeh_uniforms[ "aspect" ].value = window.innerWidth / height;
+					width: width,
+					height: height
+				} );
 
 
-				postprocessing.materialBokeh = new THREE.ShaderMaterial( {
+				bokehPass.renderToScreen = true;
 
 
-					uniforms: postprocessing.bokeh_uniforms,
-					vertexShader: bokeh_shader.vertexShader,
-					fragmentShader: bokeh_shader.fragmentShader
+				var composer = new THREE.EffectComposer( renderer );
 
 
-				} );
+				composer.addPass( renderPass );
+				composer.addPass( bokehPass );
 
 
-				postprocessing.quad = new THREE.Mesh( new THREE.PlaneGeometry( window.innerWidth, window.innerHeight ), postprocessing.materialBokeh );
-				postprocessing.quad.position.z = - 500;
-				postprocessing.scene.add( postprocessing.quad );
+				postprocessing.composer = composer;
+				postprocessing.bokeh = bokehPass;
 
 
 			}
 			}
 
 
@@ -300,22 +314,7 @@
 
 
 				if ( postprocessing.enabled ) {
 				if ( postprocessing.enabled ) {
 
 
-					renderer.clear();
-
-					// Render scene into texture
-
-					scene.overrideMaterial = null;
-					renderer.render( scene, camera, postprocessing.rtTextureColor, true );
-
-					// Render depth into texture
-
-					scene.overrideMaterial = material_depth;
-					renderer.render( scene, camera, postprocessing.rtTextureDepth, true );
-
-					// Render bokeh composite
-
-					renderer.render( postprocessing.scene, postprocessing.camera );
-
+					postprocessing.composer.render( 0.1 );
 
 
 				} else {
 				} else {
 
 
@@ -326,7 +325,6 @@
 
 
 			}
 			}
 
 
-
 		</script>
 		</script>
 	</body>
 	</body>
 </html>
 </html>

+ 25 - 12
examples/webgl_sprites.html

@@ -34,10 +34,14 @@
 
 
 			function init() {
 			function init() {
 
 
-				camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 2100 );
+				var width = window.innerWidth;
+				var height = window.innerHeight;
+
+				camera = new THREE.PerspectiveCamera( 60, width / height, 1, 2100 );
 				camera.position.z = 1500;
 				camera.position.z = 1500;
 
 
-				cameraOrtho = new THREE.OrthographicCamera( 0, window.innerWidth, window.innerHeight, 0, - 10, 10 );
+				cameraOrtho = new THREE.OrthographicCamera( - width / 2, width / 2, height / 2, - height / 2, 1, 10 );
+				cameraOrtho.position.z = 10;
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
 				scene.fog = new THREE.Fog( 0x000000, 1500, 2100 );
 				scene.fog = new THREE.Fog( 0x000000, 1500, 2100 );
@@ -137,26 +141,34 @@
 
 
 			function updateHUDSprites () {
 			function updateHUDSprites () {
 
 
+				var width = window.innerWidth / 2;
+				var height = window.innerHeight / 2;
+
 				var material = spriteTL.material;
 				var material = spriteTL.material;
 
 
-				var widthHalf = material.map.image.width / 2;
-				var heightHalf = material.map.image.height / 2;
+				var imageWidth = material.map.image.width / 2;
+				var imageHeight = material.map.image.height / 2;
 
 
-				spriteTL.position.set( widthHalf, window.innerHeight - heightHalf, 1 ); // top left
-				spriteTR.position.set( window.innerWidth - widthHalf, window.innerHeight - heightHalf, 2 ); // top right
-				spriteBL.position.set( widthHalf, heightHalf, 0 ); // bottom left
-				spriteBR.position.set( window.innerWidth - widthHalf, heightHalf, 3 ); // bottom right
-				spriteC.position.set( window.innerWidth * 0.5, window.innerHeight * 0.5, 4 ); // center
+				spriteTL.position.set( - width + imageWidth,   height - imageHeight, 1 ); // top left
+				spriteTR.position.set(   width - imageWidth,   height - imageHeight, 1 ); // top right
+				spriteBL.position.set( - width + imageWidth, - height + imageHeight, 1 ); // bottom left
+				spriteBR.position.set(   width - imageWidth, - height + imageHeight, 1 ); // bottom right
+				spriteC.position.set( 0, 0, 1 ); // center
 
 
 			};
 			};
 
 
 			function onWindowResize() {
 			function onWindowResize() {
 
 
-				camera.aspect = window.innerWidth / window.innerHeight;				
+				var width = window.innerWidth;
+				var height = window.innerHeight;
+
+				camera.aspect = width / height;				
 				camera.updateProjectionMatrix();
 				camera.updateProjectionMatrix();
 
 
-				cameraOrtho.right = window.innerWidth;
-				cameraOrtho.top = window.innerHeight;
+				cameraOrtho.left = - width / 2;
+				cameraOrtho.right = width / 2;
+				cameraOrtho.top = height / 2;
+				cameraOrtho.bottom = - height / 2;
 				cameraOrtho.updateProjectionMatrix();
 				cameraOrtho.updateProjectionMatrix();
 
 
 				updateHUDSprites();
 				updateHUDSprites();
@@ -209,6 +221,7 @@
 
 
 				renderer.clear();
 				renderer.clear();
 				renderer.render( scene, camera );
 				renderer.render( scene, camera );
+				renderer.clearDepth();
 				renderer.render( sceneOrtho, cameraOrtho );
 				renderer.render( sceneOrtho, cameraOrtho );
 
 
 			}
 			}

+ 1 - 1
index.html

@@ -95,7 +95,7 @@
 		</script>
 		</script>
 
 
 		<div id="panel">
 		<div id="panel">
-			<h1>three.js<span style="font-size: 50%; vertical-align: super;"> <a href="http://github.com/mrdoob/three.js/releases">r63</a></span></h1>
+			<h1>three.js<span style="font-size: 50%; vertical-align: super;"> <a href="http://github.com/mrdoob/three.js/releases">r64</a></span></h1>
 
 
 			<a href="examples/">examples</a><br /><br />
 			<a href="examples/">examples</a><br /><br />
 
 

Some files were not shown because too many files changed in this diff