Browse Source

merge dev

Lewy Blue 6 years ago
parent
commit
1c66840124

+ 183 - 83
build/three.js

@@ -185,7 +185,7 @@
 
 
 	} );
 	} );
 
 
-	var REVISION = '97';
+	var REVISION = '98dev';
 	var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };
 	var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };
 	var CullFaceNone = 0;
 	var CullFaceNone = 0;
 	var CullFaceBack = 1;
 	var CullFaceBack = 1;
@@ -3666,7 +3666,11 @@
 
 
 			var canvas;
 			var canvas;
 
 
-			if ( image instanceof HTMLCanvasElement ) {
+			if ( typeof HTMLCanvasElement == 'undefined' ) {
+
+				return image.src;
+
+			} else if ( image instanceof HTMLCanvasElement ) {
 
 
 				canvas = image;
 				canvas = image;
 
 
@@ -21260,7 +21264,66 @@
 
 
 		constructor: ArrayCamera,
 		constructor: ArrayCamera,
 
 
-		isArrayCamera: true
+		isArrayCamera: true,
+
+		/**
+		 * Assumes 2 cameras that are perpendicular and share an X-axis, and that
+		 * the cameras' projection and world matrices have already been set.
+		 * And that near and far planes are identical for both cameras.
+		 */
+		setProjectionFromUnion: function () {
+			var cameraLPos = new Vector3();
+			var cameraRPos = new Vector3();
+
+			return function () {
+				cameraLPos.setFromMatrixPosition( this.cameras[ 0 ].matrixWorld );
+				cameraRPos.setFromMatrixPosition( this.cameras[ 1 ].matrixWorld );
+
+				var ipd = cameraLPos.distanceTo( cameraRPos );
+
+				var projL = this.cameras[ 0 ].projectionMatrix;
+				var projR = this.cameras[ 1 ].projectionMatrix;
+
+				// VR systems will have identical far and near planes, and
+				// most likely identical top and bottom frustum extents.
+				// via: https://computergraphics.stackexchange.com/a/4765
+				var near = projL[ 14 ] / ( projL[ 10 ] - 1 );
+				var far = projL[ 14 ] / ( projL[ 10 ] + 1 );
+
+				var leftFovL = ( projL[ 8 ] - 1 ) / projL[ 0 ];
+				var rightFovR = ( projR[ 8 ] + 1 ) / projR[ 0 ];
+				var leftL = leftFovL * near;
+				var rightR = rightFovR * near;
+				var topL = near * ( projL[ 9 ] + 1 ) / projL[ 5 ];
+				var topR = near * ( projR[ 9 ] + 1 ) / projR[ 5 ];
+				var bottomL = near * ( projL[ 9 ] - 1 ) / projL[ 5 ];
+				var bottomR = near * ( projR[ 9 ] - 1 ) / projR[ 5 ];
+
+				// Calculate the new camera's position offset from the
+				// left camera.
+				var zOffset = ipd / (leftFovL + rightFovR);
+				var xOffset = zOffset * leftFovL;
+
+				// TODO: Better way to apply this offset?
+				this.cameras[ 0 ].matrixWorld.decompose( this.position, this.quaternion, this.scale );
+				this.translateX(xOffset);
+				this.translateZ(-zOffset);
+				this.matrixWorld.compose( this.position, this.quaternion, this.scale );
+				this.matrixWorldInverse.getInverse(this.matrixWorld);
+
+				// Find the union of the frustum values of the cameras and scale
+				// the values so that the near plane's position does not change in world space,
+				// although must now be relative to the new union camera.
+				var near2 = near + zOffset;
+				var far2 = far + zOffset;
+				var left = leftL - xOffset;
+				var right = rightR + (ipd - xOffset);
+				var top = Math.max( topL, topR );
+				var bottom = Math.min( bottomL, bottomR );
+
+				this.projectionMatrix.makePerspective( left, right, top, bottom, near2, far2 );
+			}
+		}(),
 
 
 	} );
 	} );
 
 
@@ -21547,9 +21610,6 @@
 			cameraL.far = camera.far;
 			cameraL.far = camera.far;
 			cameraR.far = camera.far;
 			cameraR.far = camera.far;
 
 
-			cameraVR.matrixWorld.copy( camera.matrixWorld );
-			cameraVR.matrixWorldInverse.copy( camera.matrixWorldInverse );
-
 			cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix );
 			cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix );
 			cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix );
 			cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix );
 
 
@@ -21583,10 +21643,7 @@
 			cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix );
 			cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix );
 			cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix );
 			cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix );
 
 
-			// HACK (mrdoob)
-			// https://github.com/w3c/webvr/issues/203
-
-			cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
+			cameraVR.setProjectionFromUnion();
 
 
 			//
 			//
 
 
@@ -21809,8 +21866,6 @@
 				var parent = camera.parent;
 				var parent = camera.parent;
 				var cameras = cameraVR.cameras;
 				var cameras = cameraVR.cameras;
 
 
-				// apply camera.parent to cameraVR
-
 				updateCamera( cameraVR, parent );
 				updateCamera( cameraVR, parent );
 
 
 				for ( var i = 0; i < cameras.length; i ++ ) {
 				for ( var i = 0; i < cameras.length; i ++ ) {
@@ -21831,6 +21886,8 @@
 
 
 				}
 				}
 
 
+				cameraVR.setProjectionFromUnion();
+
 				return cameraVR;
 				return cameraVR;
 
 
 			}
 			}
@@ -21869,11 +21926,6 @@
 
 
 						cameraVR.matrix.copy( camera.matrix );
 						cameraVR.matrix.copy( camera.matrix );
 
 
-						// HACK (mrdoob)
-						// https://github.com/w3c/webvr/issues/203
-
-						cameraVR.projectionMatrix.copy( camera.projectionMatrix );
-
 					}
 					}
 
 
 				}
 				}
@@ -32088,9 +32140,9 @@
 				var isBase64 = !! dataUriRegexResult[ 2 ];
 				var isBase64 = !! dataUriRegexResult[ 2 ];
 				var data = dataUriRegexResult[ 3 ];
 				var data = dataUriRegexResult[ 3 ];
 
 
-				data = window.decodeURIComponent( data );
+				data = decodeURIComponent( data );
 
 
-				if ( isBase64 ) data = window.atob( data );
+				if ( isBase64 ) data = atob( data );
 
 
 				try {
 				try {
 
 
@@ -32144,7 +32196,7 @@
 					}
 					}
 
 
 					// Wait for next browser tick like standard XMLHttpRequest event dispatching does
 					// Wait for next browser tick like standard XMLHttpRequest event dispatching does
-					window.setTimeout( function () {
+					setTimeout( function () {
 
 
 						if ( onLoad ) onLoad( response );
 						if ( onLoad ) onLoad( response );
 
 
@@ -32155,7 +32207,7 @@
 				} catch ( error ) {
 				} catch ( error ) {
 
 
 					// Wait for next browser tick like standard XMLHttpRequest event dispatching does
 					// Wait for next browser tick like standard XMLHttpRequest event dispatching does
-					window.setTimeout( function () {
+					setTimeout( function () {
 
 
 						if ( onError ) onError( error );
 						if ( onError ) onError( error );
 
 
@@ -32492,7 +32544,7 @@
 
 
 			var loader = new FileLoader( this.manager );
 			var loader = new FileLoader( this.manager );
 			loader.setResponseType( 'arraybuffer' );
 			loader.setResponseType( 'arraybuffer' );
-
+			loader.setPath( this.path );
 			loader.load( url, function ( buffer ) {
 			loader.load( url, function ( buffer ) {
 
 
 				var texData = scope._parser( buffer );
 				var texData = scope._parser( buffer );
@@ -32551,6 +32603,13 @@
 
 
 			return texture;
 			return texture;
 
 
+		},
+
+		setPath: function ( value ) {
+
+			this.path = value;
+			return this;
+
 		}
 		}
 
 
 	} );
 	} );
@@ -37128,6 +37187,7 @@
 			var scope = this;
 			var scope = this;
 
 
 			var loader = new FileLoader( scope.manager );
 			var loader = new FileLoader( scope.manager );
+			loader.setPath( scope.path );
 			loader.load( url, function ( text ) {
 			loader.load( url, function ( text ) {
 
 
 				onLoad( scope.parse( JSON.parse( text ) ) );
 				onLoad( scope.parse( JSON.parse( text ) ) );
@@ -37136,12 +37196,6 @@
 
 
 		},
 		},
 
 
-		setTextures: function ( value ) {
-
-			this.textures = value;
-
-		},
-
 		parse: function ( json ) {
 		parse: function ( json ) {
 
 
 			var textures = this.textures;
 			var textures = this.textures;
@@ -37322,10 +37376,67 @@
 
 
 			return material;
 			return material;
 
 
+		},
+
+		setPath: function ( value ) {
+
+			this.path = value;
+			return this;
+
+		},
+
+		setTextures: function ( value ) {
+
+			this.textures = value;
+			return this;
+
 		}
 		}
 
 
 	} );
 	} );
 
 
+	/**
+	 * @author Don McCurdy / https://www.donmccurdy.com
+	 */
+
+	var LoaderUtils = {
+
+		decodeText: function ( array ) {
+
+			if ( typeof TextDecoder !== 'undefined' ) {
+
+				return new TextDecoder().decode( array );
+
+			}
+
+			// Avoid the String.fromCharCode.apply(null, array) shortcut, which
+			// throws a "maximum call stack size exceeded" error for large arrays.
+
+			var s = '';
+
+			for ( var i = 0, il = array.length; i < il; i ++ ) {
+
+				// Implicitly assumes little-endian.
+				s += String.fromCharCode( array[ i ] );
+
+			}
+
+			// Merges multi-byte utf-8 characters.
+			return decodeURIComponent( escape( s ) );
+
+		},
+
+		extractUrlBase: function ( url ) {
+
+			var index = url.lastIndexOf( '/' );
+
+			if ( index === - 1 ) return './';
+
+			return url.substr( 0, index + 1 );
+
+		}
+
+	};
+
 	/**
 	/**
 	 * @author mrdoob / http://mrdoob.com/
 	 * @author mrdoob / http://mrdoob.com/
 	 */
 	 */
@@ -37343,6 +37454,7 @@
 			var scope = this;
 			var scope = this;
 
 
 			var loader = new FileLoader( scope.manager );
 			var loader = new FileLoader( scope.manager );
+			loader.setPath( scope.path );
 			loader.load( url, function ( text ) {
 			loader.load( url, function ( text ) {
 
 
 				onLoad( scope.parse( JSON.parse( text ) ) );
 				onLoad( scope.parse( JSON.parse( text ) ) );
@@ -37407,6 +37519,13 @@
 
 
 			return geometry;
 			return geometry;
 
 
+		},
+
+		setPath: function ( value ) {
+
+			this.path = value;
+			return this;
+
 		}
 		}
 
 
 	} );
 	} );
@@ -37743,49 +37862,6 @@
 
 
 	} );
 	} );
 
 
-	/**
-	 * @author Don McCurdy / https://www.donmccurdy.com
-	 */
-
-	var LoaderUtils = {
-
-		decodeText: function ( array ) {
-
-			if ( typeof TextDecoder !== 'undefined' ) {
-
-				return new TextDecoder().decode( array );
-
-			}
-
-			// Avoid the String.fromCharCode.apply(null, array) shortcut, which
-			// throws a "maximum call stack size exceeded" error for large arrays.
-
-			var s = '';
-
-			for ( var i = 0, il = array.length; i < il; i ++ ) {
-
-				// Implicitly assumes little-endian.
-				s += String.fromCharCode( array[ i ] );
-
-			}
-
-			// Merges multi-byte utf-8 characters.
-			return decodeURIComponent( escape( s ) );
-
-		},
-
-		extractUrlBase: function ( url ) {
-
-			var index = url.lastIndexOf( '/' );
-
-			if ( index === - 1 ) return './';
-
-			return url.substr( 0, index + 1 );
-
-		}
-
-	};
-
 	/**
 	/**
 	 * @author mrdoob / http://mrdoob.com/
 	 * @author mrdoob / http://mrdoob.com/
 	 * @author alteredq / http://alteredqualia.com/
 	 * @author alteredq / http://alteredqualia.com/
@@ -38366,7 +38442,7 @@
 	function ObjectLoader( manager ) {
 	function ObjectLoader( manager ) {
 
 
 		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
 		this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
-		this.texturePath = '';
+		this.resourcePath = '';
 
 
 	}
 	}
 
 
@@ -38376,15 +38452,13 @@
 
 
 		load: function ( url, onLoad, onProgress, onError ) {
 		load: function ( url, onLoad, onProgress, onError ) {
 
 
-			if ( this.texturePath === '' ) {
-
-				this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 );
-
-			}
-
 			var scope = this;
 			var scope = this;
 
 
+			var path = ( this.path === undefined ) ? LoaderUtils.extractUrlBase( url ) : this.path;
+			this.resourcePath = this.resourcePath || path;
+
 			var loader = new FileLoader( scope.manager );
 			var loader = new FileLoader( scope.manager );
+			loader.setPath( this.path );
 			loader.load( url, function ( text ) {
 			loader.load( url, function ( text ) {
 
 
 				var json = null;
 				var json = null;
@@ -38418,9 +38492,16 @@
 
 
 		},
 		},
 
 
-		setTexturePath: function ( value ) {
+		setPath: function ( value ) {
+
+			this.path = value;
+			return this;
+
+		},
 
 
-			this.texturePath = value;
+		setResourcePath: function ( value ) {
+
+			this.resourcePath = value;
 			return this;
 			return this;
 
 
 		},
 		},
@@ -38723,7 +38804,7 @@
 
 
 						case 'Geometry':
 						case 'Geometry':
 
 
-							geometry = geometryLoader.parse( data, this.texturePath ).geometry;
+							geometry = geometryLoader.parse( data, this.resourcePath ).geometry;
 
 
 							break;
 							break;
 
 
@@ -38855,7 +38936,7 @@
 
 
 							var currentUrl = url[ j ];
 							var currentUrl = url[ j ];
 
 
-							var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( currentUrl ) ? currentUrl : scope.texturePath + currentUrl;
+							var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( currentUrl ) ? currentUrl : scope.resourcePath + currentUrl;
 
 
 							images[ image.uuid ].push( loadImage( path ) );
 							images[ image.uuid ].push( loadImage( path ) );
 
 
@@ -38865,7 +38946,7 @@
 
 
 						// load single image
 						// load single image
 
 
-						var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url;
+						var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.resourcePath + image.url;
 
 
 						images[ image.uuid ] = loadImage( path );
 						images[ image.uuid ] = loadImage( path );
 
 
@@ -39900,6 +39981,7 @@
 
 
 			var loader = new FileLoader( this.manager );
 			var loader = new FileLoader( this.manager );
 			loader.setResponseType( 'arraybuffer' );
 			loader.setResponseType( 'arraybuffer' );
+			loader.setPath( this.path );
 			loader.load( url, function ( buffer ) {
 			loader.load( url, function ( buffer ) {
 
 
 				// Create a copy of the buffer. The `decodeAudioData` method
 				// Create a copy of the buffer. The `decodeAudioData` method
@@ -39915,6 +39997,13 @@
 
 
 			}, onProgress, onError );
 			}, onProgress, onError );
 
 
+		},
+
+		setPath: function ( value ) {
+
+			this.path = value;
+			return this;
+
 		}
 		}
 
 
 	} );
 	} );
@@ -46168,6 +46257,17 @@
 
 
 	} );
 	} );
 
 
+	Object.assign( ObjectLoader.prototype, {
+
+		setTexturePath: function ( value ) {
+
+			console.warn( 'THREE.ObjectLoader: .setTexturePath() has been renamed to .setResourcePath().' );
+			return this.setResourcePath( value );
+
+		}
+
+	} );
+
 	//
 	//
 
 
 	Object.assign( Box2.prototype, {
 	Object.assign( Box2.prototype, {

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


+ 183 - 83
build/three.module.js

@@ -179,7 +179,7 @@ Object.assign( EventDispatcher.prototype, {
 
 
 } );
 } );
 
 
-var REVISION = '97';
+var REVISION = '98dev';
 var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };
 var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };
 var CullFaceNone = 0;
 var CullFaceNone = 0;
 var CullFaceBack = 1;
 var CullFaceBack = 1;
@@ -3660,7 +3660,11 @@ var ImageUtils = {
 
 
 		var canvas;
 		var canvas;
 
 
-		if ( image instanceof HTMLCanvasElement ) {
+		if ( typeof HTMLCanvasElement == 'undefined' ) {
+
+			return image.src;
+
+		} else if ( image instanceof HTMLCanvasElement ) {
 
 
 			canvas = image;
 			canvas = image;
 
 
@@ -21254,7 +21258,66 @@ ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototyp
 
 
 	constructor: ArrayCamera,
 	constructor: ArrayCamera,
 
 
-	isArrayCamera: true
+	isArrayCamera: true,
+
+	/**
+	 * Assumes 2 cameras that are perpendicular and share an X-axis, and that
+	 * the cameras' projection and world matrices have already been set.
+	 * And that near and far planes are identical for both cameras.
+	 */
+	setProjectionFromUnion: function () {
+		var cameraLPos = new Vector3();
+		var cameraRPos = new Vector3();
+
+		return function () {
+			cameraLPos.setFromMatrixPosition( this.cameras[ 0 ].matrixWorld );
+			cameraRPos.setFromMatrixPosition( this.cameras[ 1 ].matrixWorld );
+
+			var ipd = cameraLPos.distanceTo( cameraRPos );
+
+			var projL = this.cameras[ 0 ].projectionMatrix;
+			var projR = this.cameras[ 1 ].projectionMatrix;
+
+			// VR systems will have identical far and near planes, and
+			// most likely identical top and bottom frustum extents.
+			// via: https://computergraphics.stackexchange.com/a/4765
+			var near = projL[ 14 ] / ( projL[ 10 ] - 1 );
+			var far = projL[ 14 ] / ( projL[ 10 ] + 1 );
+
+			var leftFovL = ( projL[ 8 ] - 1 ) / projL[ 0 ];
+			var rightFovR = ( projR[ 8 ] + 1 ) / projR[ 0 ];
+			var leftL = leftFovL * near;
+			var rightR = rightFovR * near;
+			var topL = near * ( projL[ 9 ] + 1 ) / projL[ 5 ];
+			var topR = near * ( projR[ 9 ] + 1 ) / projR[ 5 ];
+			var bottomL = near * ( projL[ 9 ] - 1 ) / projL[ 5 ];
+			var bottomR = near * ( projR[ 9 ] - 1 ) / projR[ 5 ];
+
+			// Calculate the new camera's position offset from the
+			// left camera.
+			var zOffset = ipd / (leftFovL + rightFovR);
+			var xOffset = zOffset * leftFovL;
+
+			// TODO: Better way to apply this offset?
+			this.cameras[ 0 ].matrixWorld.decompose( this.position, this.quaternion, this.scale );
+			this.translateX(xOffset);
+			this.translateZ(-zOffset);
+			this.matrixWorld.compose( this.position, this.quaternion, this.scale );
+			this.matrixWorldInverse.getInverse(this.matrixWorld);
+
+			// Find the union of the frustum values of the cameras and scale
+			// the values so that the near plane's position does not change in world space,
+			// although must now be relative to the new union camera.
+			var near2 = near + zOffset;
+			var far2 = far + zOffset;
+			var left = leftL - xOffset;
+			var right = rightR + (ipd - xOffset);
+			var top = Math.max( topL, topR );
+			var bottom = Math.min( bottomL, bottomR );
+
+			this.projectionMatrix.makePerspective( left, right, top, bottom, near2, far2 );
+		}
+	}(),
 
 
 } );
 } );
 
 
@@ -21541,9 +21604,6 @@ function WebVRManager( renderer ) {
 		cameraL.far = camera.far;
 		cameraL.far = camera.far;
 		cameraR.far = camera.far;
 		cameraR.far = camera.far;
 
 
-		cameraVR.matrixWorld.copy( camera.matrixWorld );
-		cameraVR.matrixWorldInverse.copy( camera.matrixWorldInverse );
-
 		cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix );
 		cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix );
 		cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix );
 		cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix );
 
 
@@ -21577,10 +21637,7 @@ function WebVRManager( renderer ) {
 		cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix );
 		cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix );
 		cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix );
 		cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix );
 
 
-		// HACK (mrdoob)
-		// https://github.com/w3c/webvr/issues/203
-
-		cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
+		cameraVR.setProjectionFromUnion();
 
 
 		//
 		//
 
 
@@ -21803,8 +21860,6 @@ function WebXRManager( renderer ) {
 			var parent = camera.parent;
 			var parent = camera.parent;
 			var cameras = cameraVR.cameras;
 			var cameras = cameraVR.cameras;
 
 
-			// apply camera.parent to cameraVR
-
 			updateCamera( cameraVR, parent );
 			updateCamera( cameraVR, parent );
 
 
 			for ( var i = 0; i < cameras.length; i ++ ) {
 			for ( var i = 0; i < cameras.length; i ++ ) {
@@ -21825,6 +21880,8 @@ function WebXRManager( renderer ) {
 
 
 			}
 			}
 
 
+			cameraVR.setProjectionFromUnion();
+
 			return cameraVR;
 			return cameraVR;
 
 
 		}
 		}
@@ -21863,11 +21920,6 @@ function WebXRManager( renderer ) {
 
 
 					cameraVR.matrix.copy( camera.matrix );
 					cameraVR.matrix.copy( camera.matrix );
 
 
-					// HACK (mrdoob)
-					// https://github.com/w3c/webvr/issues/203
-
-					cameraVR.projectionMatrix.copy( camera.projectionMatrix );
-
 				}
 				}
 
 
 			}
 			}
@@ -32082,9 +32134,9 @@ Object.assign( FileLoader.prototype, {
 			var isBase64 = !! dataUriRegexResult[ 2 ];
 			var isBase64 = !! dataUriRegexResult[ 2 ];
 			var data = dataUriRegexResult[ 3 ];
 			var data = dataUriRegexResult[ 3 ];
 
 
-			data = window.decodeURIComponent( data );
+			data = decodeURIComponent( data );
 
 
-			if ( isBase64 ) data = window.atob( data );
+			if ( isBase64 ) data = atob( data );
 
 
 			try {
 			try {
 
 
@@ -32138,7 +32190,7 @@ Object.assign( FileLoader.prototype, {
 				}
 				}
 
 
 				// Wait for next browser tick like standard XMLHttpRequest event dispatching does
 				// Wait for next browser tick like standard XMLHttpRequest event dispatching does
-				window.setTimeout( function () {
+				setTimeout( function () {
 
 
 					if ( onLoad ) onLoad( response );
 					if ( onLoad ) onLoad( response );
 
 
@@ -32149,7 +32201,7 @@ Object.assign( FileLoader.prototype, {
 			} catch ( error ) {
 			} catch ( error ) {
 
 
 				// Wait for next browser tick like standard XMLHttpRequest event dispatching does
 				// Wait for next browser tick like standard XMLHttpRequest event dispatching does
-				window.setTimeout( function () {
+				setTimeout( function () {
 
 
 					if ( onError ) onError( error );
 					if ( onError ) onError( error );
 
 
@@ -32486,7 +32538,7 @@ Object.assign( DataTextureLoader.prototype, {
 
 
 		var loader = new FileLoader( this.manager );
 		var loader = new FileLoader( this.manager );
 		loader.setResponseType( 'arraybuffer' );
 		loader.setResponseType( 'arraybuffer' );
-
+		loader.setPath( this.path );
 		loader.load( url, function ( buffer ) {
 		loader.load( url, function ( buffer ) {
 
 
 			var texData = scope._parser( buffer );
 			var texData = scope._parser( buffer );
@@ -32545,6 +32597,13 @@ Object.assign( DataTextureLoader.prototype, {
 
 
 		return texture;
 		return texture;
 
 
+	},
+
+	setPath: function ( value ) {
+
+		this.path = value;
+		return this;
+
 	}
 	}
 
 
 } );
 } );
@@ -37122,6 +37181,7 @@ Object.assign( MaterialLoader.prototype, {
 		var scope = this;
 		var scope = this;
 
 
 		var loader = new FileLoader( scope.manager );
 		var loader = new FileLoader( scope.manager );
+		loader.setPath( scope.path );
 		loader.load( url, function ( text ) {
 		loader.load( url, function ( text ) {
 
 
 			onLoad( scope.parse( JSON.parse( text ) ) );
 			onLoad( scope.parse( JSON.parse( text ) ) );
@@ -37130,12 +37190,6 @@ Object.assign( MaterialLoader.prototype, {
 
 
 	},
 	},
 
 
-	setTextures: function ( value ) {
-
-		this.textures = value;
-
-	},
-
 	parse: function ( json ) {
 	parse: function ( json ) {
 
 
 		var textures = this.textures;
 		var textures = this.textures;
@@ -37316,10 +37370,67 @@ Object.assign( MaterialLoader.prototype, {
 
 
 		return material;
 		return material;
 
 
+	},
+
+	setPath: function ( value ) {
+
+		this.path = value;
+		return this;
+
+	},
+
+	setTextures: function ( value ) {
+
+		this.textures = value;
+		return this;
+
 	}
 	}
 
 
 } );
 } );
 
 
+/**
+ * @author Don McCurdy / https://www.donmccurdy.com
+ */
+
+var LoaderUtils = {
+
+	decodeText: function ( array ) {
+
+		if ( typeof TextDecoder !== 'undefined' ) {
+
+			return new TextDecoder().decode( array );
+
+		}
+
+		// Avoid the String.fromCharCode.apply(null, array) shortcut, which
+		// throws a "maximum call stack size exceeded" error for large arrays.
+
+		var s = '';
+
+		for ( var i = 0, il = array.length; i < il; i ++ ) {
+
+			// Implicitly assumes little-endian.
+			s += String.fromCharCode( array[ i ] );
+
+		}
+
+		// Merges multi-byte utf-8 characters.
+		return decodeURIComponent( escape( s ) );
+
+	},
+
+	extractUrlBase: function ( url ) {
+
+		var index = url.lastIndexOf( '/' );
+
+		if ( index === - 1 ) return './';
+
+		return url.substr( 0, index + 1 );
+
+	}
+
+};
+
 /**
 /**
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  */
  */
@@ -37337,6 +37448,7 @@ Object.assign( BufferGeometryLoader.prototype, {
 		var scope = this;
 		var scope = this;
 
 
 		var loader = new FileLoader( scope.manager );
 		var loader = new FileLoader( scope.manager );
+		loader.setPath( scope.path );
 		loader.load( url, function ( text ) {
 		loader.load( url, function ( text ) {
 
 
 			onLoad( scope.parse( JSON.parse( text ) ) );
 			onLoad( scope.parse( JSON.parse( text ) ) );
@@ -37401,6 +37513,13 @@ Object.assign( BufferGeometryLoader.prototype, {
 
 
 		return geometry;
 		return geometry;
 
 
+	},
+
+	setPath: function ( value ) {
+
+		this.path = value;
+		return this;
+
 	}
 	}
 
 
 } );
 } );
@@ -37737,49 +37856,6 @@ Object.assign( Loader.prototype, {
 
 
 } );
 } );
 
 
-/**
- * @author Don McCurdy / https://www.donmccurdy.com
- */
-
-var LoaderUtils = {
-
-	decodeText: function ( array ) {
-
-		if ( typeof TextDecoder !== 'undefined' ) {
-
-			return new TextDecoder().decode( array );
-
-		}
-
-		// Avoid the String.fromCharCode.apply(null, array) shortcut, which
-		// throws a "maximum call stack size exceeded" error for large arrays.
-
-		var s = '';
-
-		for ( var i = 0, il = array.length; i < il; i ++ ) {
-
-			// Implicitly assumes little-endian.
-			s += String.fromCharCode( array[ i ] );
-
-		}
-
-		// Merges multi-byte utf-8 characters.
-		return decodeURIComponent( escape( s ) );
-
-	},
-
-	extractUrlBase: function ( url ) {
-
-		var index = url.lastIndexOf( '/' );
-
-		if ( index === - 1 ) return './';
-
-		return url.substr( 0, index + 1 );
-
-	}
-
-};
-
 /**
 /**
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  * @author alteredq / http://alteredqualia.com/
  * @author alteredq / http://alteredqualia.com/
@@ -38360,7 +38436,7 @@ Object.assign( JSONLoader.prototype, {
 function ObjectLoader( manager ) {
 function ObjectLoader( manager ) {
 
 
 	this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
 	this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
-	this.texturePath = '';
+	this.resourcePath = '';
 
 
 }
 }
 
 
@@ -38370,15 +38446,13 @@ Object.assign( ObjectLoader.prototype, {
 
 
 	load: function ( url, onLoad, onProgress, onError ) {
 	load: function ( url, onLoad, onProgress, onError ) {
 
 
-		if ( this.texturePath === '' ) {
-
-			this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 );
-
-		}
-
 		var scope = this;
 		var scope = this;
 
 
+		var path = ( this.path === undefined ) ? LoaderUtils.extractUrlBase( url ) : this.path;
+		this.resourcePath = this.resourcePath || path;
+
 		var loader = new FileLoader( scope.manager );
 		var loader = new FileLoader( scope.manager );
+		loader.setPath( this.path );
 		loader.load( url, function ( text ) {
 		loader.load( url, function ( text ) {
 
 
 			var json = null;
 			var json = null;
@@ -38412,9 +38486,16 @@ Object.assign( ObjectLoader.prototype, {
 
 
 	},
 	},
 
 
-	setTexturePath: function ( value ) {
+	setPath: function ( value ) {
+
+		this.path = value;
+		return this;
+
+	},
 
 
-		this.texturePath = value;
+	setResourcePath: function ( value ) {
+
+		this.resourcePath = value;
 		return this;
 		return this;
 
 
 	},
 	},
@@ -38717,7 +38798,7 @@ Object.assign( ObjectLoader.prototype, {
 
 
 					case 'Geometry':
 					case 'Geometry':
 
 
-						geometry = geometryLoader.parse( data, this.texturePath ).geometry;
+						geometry = geometryLoader.parse( data, this.resourcePath ).geometry;
 
 
 						break;
 						break;
 
 
@@ -38849,7 +38930,7 @@ Object.assign( ObjectLoader.prototype, {
 
 
 						var currentUrl = url[ j ];
 						var currentUrl = url[ j ];
 
 
-						var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( currentUrl ) ? currentUrl : scope.texturePath + currentUrl;
+						var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( currentUrl ) ? currentUrl : scope.resourcePath + currentUrl;
 
 
 						images[ image.uuid ].push( loadImage( path ) );
 						images[ image.uuid ].push( loadImage( path ) );
 
 
@@ -38859,7 +38940,7 @@ Object.assign( ObjectLoader.prototype, {
 
 
 					// load single image
 					// load single image
 
 
-					var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url;
+					var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.resourcePath + image.url;
 
 
 					images[ image.uuid ] = loadImage( path );
 					images[ image.uuid ] = loadImage( path );
 
 
@@ -39894,6 +39975,7 @@ Object.assign( AudioLoader.prototype, {
 
 
 		var loader = new FileLoader( this.manager );
 		var loader = new FileLoader( this.manager );
 		loader.setResponseType( 'arraybuffer' );
 		loader.setResponseType( 'arraybuffer' );
+		loader.setPath( this.path );
 		loader.load( url, function ( buffer ) {
 		loader.load( url, function ( buffer ) {
 
 
 			// Create a copy of the buffer. The `decodeAudioData` method
 			// Create a copy of the buffer. The `decodeAudioData` method
@@ -39909,6 +39991,13 @@ Object.assign( AudioLoader.prototype, {
 
 
 		}, onProgress, onError );
 		}, onProgress, onError );
 
 
+	},
+
+	setPath: function ( value ) {
+
+		this.path = value;
+		return this;
+
 	}
 	}
 
 
 } );
 } );
@@ -46162,6 +46251,17 @@ Object.assign( JSONLoader.prototype, {
 
 
 } );
 } );
 
 
+Object.assign( ObjectLoader.prototype, {
+
+	setTexturePath: function ( value ) {
+
+		console.warn( 'THREE.ObjectLoader: .setTexturePath() has been renamed to .setResourcePath().' );
+		return this.setResourcePath( value );
+
+	}
+
+} );
+
 //
 //
 
 
 Object.assign( Box2.prototype, {
 Object.assign( Box2.prototype, {

+ 8 - 5
docs/api/en/loaders/ObjectLoader.html

@@ -85,9 +85,9 @@
 			The [page:LoadingManager loadingManager]  the loader is using. Default is [page:DefaultLoadingManager].
 			The [page:LoadingManager loadingManager]  the loader is using. Default is [page:DefaultLoadingManager].
 		</p>
 		</p>
 
 
-		<h3>[property:String texturePath]</h3>
+		<h3>[property:String resourcePath]</h3>
 		<p>
 		<p>
-			The base path or URL from which textures will be loaded. See [page:.setTexturePath].
+			The base path or URL from which additional resources like textuures will be loaded. See [page:.setResourcePath].
 			Default is the empty string.
 			Default is the empty string.
 		</p>
 		</p>
 
 
@@ -217,11 +217,14 @@
 		[page:String value] — The crossOrigin string to implement CORS for loading the url from a different domain that allows CORS.
 		[page:String value] — The crossOrigin string to implement CORS for loading the url from a different domain that allows CORS.
 		</p>
 		</p>
 
 
-		<h3>[method:ObjectLoader setTexturePath]( [param:String value] )</h3>
+		<h3>[method:ObjectLoader setPath]( [param:String value] )</h3>
 		<p>
 		<p>
-		[page:String value] — The base path or URL from which textures will be loaded.<br /><br />
-
+			Set the base path for the original file.
+		</p>
 
 
+		<h3>[method:ObjectLoader setResourcePath]( [param:String value] )</h3>
+		<p>
+			Set the base path for dependent resources like textures.
 		</p>
 		</p>
 
 
 		<h2>Source</h2>
 		<h2>Source</h2>

+ 3 - 3
docs/manual/en/introduction/Animation-system.html

@@ -52,13 +52,13 @@
 		<p class="desc">
 		<p class="desc">
 
 
 			Inside of such an *AnimationClip* the data for each animated property are stored in a
 			Inside of such an *AnimationClip* the data for each animated property are stored in a
-			separate [page:KeyframeTrack]. Assumed a character object has a [page:Skeleton skeleton],
+			separate [page:KeyframeTrack]. Assuming a character object has a [page:Skeleton skeleton],
 			one keyframe track could store the data for the position changes of the lower arm bone
 			one keyframe track could store the data for the position changes of the lower arm bone
 			over time, a different track the data for the rotation changes of the same bone, a third
 			over time, a different track the data for the rotation changes of the same bone, a third
 			the track position, rotation or scaling of another bone, and so on. It should be clear,
 			the track position, rotation or scaling of another bone, and so on. It should be clear,
 			that an AnimationClip can be composed of lots of such tracks.<br /><br />
 			that an AnimationClip can be composed of lots of such tracks.<br /><br />
 
 
-			Assumed the model has [page:Geometry.morphTargets morph targets] (for example one morph
+			Assuming the model has [page:Geometry.morphTargets morph targets] (for example one morph
 			target showing a friendly face and another showing an angry face), each track holds the
 			target showing a friendly face and another showing an angry face), each track holds the
 			information as to how the [page:Mesh.morphTargetInfluences influence] of a certain morph
 			information as to how the [page:Mesh.morphTargetInfluences influence] of a certain morph
 			target changes during the performance of the clip.
 			target changes during the performance of the clip.
@@ -69,7 +69,7 @@
 
 
 		<p class="desc">
 		<p class="desc">
 
 
-			The stored data form only the basis for the animations - actual playback is controlled by
+			The stored data forms only the basis for the animations - actual playback is controlled by
 			the [page:AnimationMixer]. You can imagine this not only as a player for animations, but
 			the [page:AnimationMixer]. You can imagine this not only as a player for animations, but
 			as a simulation of a hardware like a real mixer console, which can control several animations
 			as a simulation of a hardware like a real mixer console, which can control several animations
 			simultaneously, blending and merging them.
 			simultaneously, blending and merging them.

+ 1 - 1
editor/js/Loader.js

@@ -626,7 +626,7 @@ var Loader = function ( editor ) {
 			case 'object':
 			case 'object':
 
 
 				var loader = new THREE.ObjectLoader();
 				var loader = new THREE.ObjectLoader();
-				loader.setTexturePath( scope.texturePath );
+				loader.setResourcePath( scope.texturePath );
 
 
 				var result = loader.parse( data );
 				var result = loader.parse( data );
 
 

+ 5 - 4
examples/files.js

@@ -42,10 +42,6 @@ var files = {
 		"webgl_geometry_terrain_raycast",
 		"webgl_geometry_terrain_raycast",
 		"webgl_geometry_text",
 		"webgl_geometry_text",
 		"webgl_geometry_text_shapes",
 		"webgl_geometry_text_shapes",
-		"webgl_gpgpu_birds",
-		"webgl_gpgpu_water",
-		"webgl_gpgpu_protoplanet",
-		"webgl_gpu_particle_system",
 		"webgl_hdr",
 		"webgl_hdr",
 		"webgl_helpers",
 		"webgl_helpers",
 		"webgl_interactive_buffergeometry",
 		"webgl_interactive_buffergeometry",
@@ -300,6 +296,10 @@ var files = {
 		"webgl_custom_attributes_points",
 		"webgl_custom_attributes_points",
 		"webgl_custom_attributes_points2",
 		"webgl_custom_attributes_points2",
 		"webgl_custom_attributes_points3",
 		"webgl_custom_attributes_points3",
+		"webgl_gpgpu_birds",
+		"webgl_gpgpu_water",
+		"webgl_gpgpu_protoplanet",
+		"webgl_gpu_particle_system",
 		"webgl_materials_modified",
 		"webgl_materials_modified",
 		"webgl_raymarching_reflect",
 		"webgl_raymarching_reflect",
 		"webgl_shadowmap_pcss",
 		"webgl_shadowmap_pcss",
@@ -325,6 +325,7 @@ var files = {
 		"webvr_ballshooter",
 		"webvr_ballshooter",
 		"webvr_cubes",
 		"webvr_cubes",
 		"webvr_dragging",
 		"webvr_dragging",
+		"webvr_frustum",
 		"webvr_lorenzattractor",
 		"webvr_lorenzattractor",
 		"webvr_panorama",
 		"webvr_panorama",
 		"webvr_paint",
 		"webvr_paint",

File diff suppressed because it is too large
+ 372 - 298
examples/js/loaders/GLTFLoader.js


+ 1 - 1
examples/webgl_gpgpu_water.html

@@ -1,4 +1,4 @@
-<!DOCTYPE html>
+ <!DOCTYPE html>
 <html lang="en">
 <html lang="en">
 	<head>
 	<head>
 		<title>three.js webgl - gpgpu - water</title>
 		<title>three.js webgl - gpgpu - water</title>

+ 1 - 1
examples/webgl_materials_cars.html

@@ -127,7 +127,7 @@
 				shadowLight.shadow.camera.bottom = -2;
 				shadowLight.shadow.camera.bottom = -2;
 				shadowLight.shadow.camera.left = -2.5;
 				shadowLight.shadow.camera.left = -2.5;
 				shadowLight.shadow.camera.right = 2.5;
 				shadowLight.shadow.camera.right = 2.5;
-				shadowLight.shadow.camera.far = 5.5;
+				shadowLight.shadow.camera.far = 5.75;
 				shadowLight.shadow.bias = -0.025;
 				shadowLight.shadow.bias = -0.025;
 
 
 				lightHolder.add( shadowLight, shadowLight.target );
 				lightHolder.add( shadowLight, shadowLight.target );

+ 2 - 2
examples/webgl_modifier_simplifier.html

@@ -67,13 +67,13 @@
 					mesh.rotation.y = Math.PI / 2;
 					mesh.rotation.y = Math.PI / 2;
 					scene.add( mesh );
 					scene.add( mesh );
 
 
-					var modifer = new THREE.SimplifyModifier();
+					var modifier = new THREE.SimplifyModifier();
 
 
 					var simplified = mesh.clone();
 					var simplified = mesh.clone();
 					simplified.material = simplified.material.clone();
 					simplified.material = simplified.material.clone();
 					simplified.material.flatShading = true;
 					simplified.material.flatShading = true;
 					var count = Math.floor( simplified.geometry.attributes.position.count * 0.875 ); // number of vertices to remove
 					var count = Math.floor( simplified.geometry.attributes.position.count * 0.875 ); // number of vertices to remove
-					simplified.geometry = modifer.modify( simplified.geometry, count );
+					simplified.geometry = modifier.modify( simplified.geometry, count );
 
 
 					simplified.position.x = 3;
 					simplified.position.x = 3;
 					simplified.rotation.y = - Math.PI / 2;
 					simplified.rotation.y = - Math.PI / 2;

+ 129 - 0
examples/webvr_frustum.html

@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webvr - frustum</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
+		<!-- Origin Trial Token, feature = WebVR (For Chrome M62+), origin = https://threejs.org, expires = 2018-09-11 -->
+		<meta http-equiv="origin-trial" data-feature="WebVR (For Chrome M62+)" data-expires="2018-09-11" content="AqhFUYKxq/d+E8CDT0fuYRCg8TvlTP52x0Jv7I9t27sLhR30LmcahBRfSwzP89ukjs2+ia99VrrLoRyaFAwJVA0AAABQeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUjEuMU02MiIsImV4cGlyeSI6MTUzNjYyNDAwMH0=">
+		<!-- Origin Trial Token, feature = WebXR Device API (For Chrome M69+), origin = https://threejs.org, expires = 2018-10-27 -->
+		<meta http-equiv="origin-trial" data-feature="WebXR Device API (For Chrome M69+)" data-expires="2018-10-27" content="An4ZYOGvf6kVHNxqZxS02TPAvpZESkmBhcVCM/byViDDuEB2XKvCF43aCJjrAU/R8H3WDlv+1bDGTL/XxstHGgoAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU02OSIsImV4cGlyeSI6MTU0MDY1NTAyMn0=">
+		<!-- Origin Trial Token, feature = WebXR Gamepad Support, origin = https://threejs.org, expires = 2018-10-24 -->
+		<meta http-equiv="origin-trial" data-feature="WebXR Gamepad Support" data-expires="2018-10-24" content="Agrr6lZhlwzv5jmv/mpLZA37DIiVcg3HvX8bH8EWB+OBruV3sUJuzDfYz6qs/je+LcH41DkrmPn4k9RaUaqpQAAAAABYeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkdhbWVwYWRTdXBwb3J0IiwiZXhwaXJ5IjoxNTQwMzg4NjI0fQ==">
+		<style>
+			body {
+				font-family: Monospace;
+				background-color: #101010;
+				color: #fff;
+				margin: 0px;
+				overflow: hidden;
+			}
+			a {
+				color: #f00;
+			}
+		</style>
+	</head>
+	<body>
+
+		<script src="../build/three.js"></script>
+		<script src="js/vr/WebVR.js"></script>
+		<script src="js/geometries/BoxLineGeometry.js"></script>
+
+		<script>
+
+			var size = 10;
+
+			var container;
+			var camera, scene, raycaster, renderer;
+
+			var room;
+
+			init();
+			animate();
+
+			function init() {
+
+				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 = '<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - interactive cubes';
+				container.appendChild( info );
+
+				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0x505050 );
+
+				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 10 );
+				scene.add( camera );
+
+				room = new THREE.LineSegments(
+					new THREE.BoxLineGeometry( 6, 6, 6, 10, 10, 10 ),
+					new THREE.LineBasicMaterial( { color: 0x808080 } )
+				);
+				room.position.y = 3;
+				scene.add( room );
+
+				scene.add( new THREE.HemisphereLight( 0x606060, 0x404040 ) );
+
+				var geometry = new THREE.BoxBufferGeometry( 0.15, 0.15, 0.15 );
+
+				for ( var x = 0; x < size; x ++ ) {
+					for ( var y = 0; y < size; y ++ ) {
+
+						var xVal = x / size;
+						var yVal = y / size;
+						var color = new THREE.Color( 1, 1, 1 );
+						color.r = x % 2;
+						color.g = y % 2;
+						color.b = 1;
+						var object = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { color: color } ));
+
+						object.position.x = xVal * 8 - 4;
+						object.position.y = yVal * 8 - 4;
+						object.position.z = -4;
+
+						room.add( object );
+
+					}
+				}
+
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.vr.enabled = true;
+				container.appendChild( renderer.domElement );
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+				document.body.appendChild( WEBVR.createButton( renderer ) );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function animate() {
+
+				renderer.setAnimationLoop( render );
+
+			}
+
+			function render() {
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+	</body>
+</html>

+ 4 - 548
package-lock.json

@@ -1,6 +1,6 @@
 {
 {
   "name": "three",
   "name": "three",
-  "version": "0.96.0",
+  "version": "0.97.0",
   "lockfileVersion": 1,
   "lockfileVersion": 1,
   "requires": true,
   "requires": true,
   "dependencies": {
   "dependencies": {
@@ -187,12 +187,6 @@
       "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
       "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
       "dev": true
       "dev": true
     },
     },
-    "async-each": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
-      "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=",
-      "dev": true
-    },
     "asynckit": {
     "asynckit": {
       "version": "0.4.0",
       "version": "0.4.0",
       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
@@ -288,12 +282,6 @@
         "tweetnacl": "^0.14.3"
         "tweetnacl": "^0.14.3"
       }
       }
     },
     },
-    "binary-extensions": {
-      "version": "1.11.0",
-      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",
-      "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=",
-      "dev": true
-    },
     "brace-expansion": {
     "brace-expansion": {
       "version": "1.1.11",
       "version": "1.1.11",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
       "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -453,124 +441,6 @@
       "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
       "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
       "dev": true
       "dev": true
     },
     },
-    "chokidar": {
-      "version": "1.7.0",
-      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz",
-      "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
-      "dev": true,
-      "requires": {
-        "anymatch": "^1.3.0",
-        "async-each": "^1.0.0",
-        "fsevents": "^1.0.0",
-        "glob-parent": "^2.0.0",
-        "inherits": "^2.0.1",
-        "is-binary-path": "^1.0.0",
-        "is-glob": "^2.0.0",
-        "path-is-absolute": "^1.0.0",
-        "readdirp": "^2.0.0"
-      },
-      "dependencies": {
-        "anymatch": {
-          "version": "1.3.2",
-          "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz",
-          "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==",
-          "dev": true,
-          "requires": {
-            "micromatch": "^2.1.5",
-            "normalize-path": "^2.0.0"
-          }
-        },
-        "arr-diff": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
-          "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
-          "dev": true,
-          "requires": {
-            "arr-flatten": "^1.0.1"
-          }
-        },
-        "array-unique": {
-          "version": "0.2.1",
-          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
-          "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
-          "dev": true
-        },
-        "braces": {
-          "version": "1.8.5",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
-          "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
-          "dev": true,
-          "requires": {
-            "expand-range": "^1.8.1",
-            "preserve": "^0.2.0",
-            "repeat-element": "^1.1.2"
-          }
-        },
-        "expand-brackets": {
-          "version": "0.1.5",
-          "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
-          "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
-          "dev": true,
-          "requires": {
-            "is-posix-bracket": "^0.1.0"
-          }
-        },
-        "extglob": {
-          "version": "0.3.2",
-          "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
-          "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^1.0.0"
-          }
-        },
-        "is-extglob": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
-          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
-          "dev": true
-        },
-        "is-glob": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
-          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^1.0.0"
-          }
-        },
-        "kind-of": {
-          "version": "3.2.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "^1.1.5"
-          }
-        },
-        "micromatch": {
-          "version": "2.3.11",
-          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
-          "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
-          "dev": true,
-          "requires": {
-            "arr-diff": "^2.0.0",
-            "array-unique": "^0.2.1",
-            "braces": "^1.8.2",
-            "expand-brackets": "^0.1.4",
-            "extglob": "^0.3.1",
-            "filename-regex": "^2.0.0",
-            "is-extglob": "^1.0.0",
-            "is-glob": "^2.0.1",
-            "kind-of": "^3.0.2",
-            "normalize-path": "^2.0.1",
-            "object.omit": "^2.0.0",
-            "parse-glob": "^3.0.4",
-            "regex-cache": "^0.4.2"
-          }
-        }
-      }
-    },
     "circular-json": {
     "circular-json": {
       "version": "0.3.3",
       "version": "0.3.3",
       "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
       "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
@@ -1243,12 +1113,6 @@
       "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
       "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=",
       "dev": true
       "dev": true
     },
     },
-    "estree-walker": {
-      "version": "0.5.2",
-      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.5.2.tgz",
-      "integrity": "sha512-XpCnW/AE10ws/kDAs37cngSkvgIR8aN3G0MS85m7dUpuK2EREo9VJ00uvw6Dg/hXEpfsE1I1TvJOJr+Z+TL+ig==",
-      "dev": true
-    },
     "esutils": {
     "esutils": {
       "version": "2.0.2",
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
       "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz",
@@ -1326,63 +1190,6 @@
         }
         }
       }
       }
     },
     },
-    "expand-range": {
-      "version": "1.8.2",
-      "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
-      "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=",
-      "dev": true,
-      "requires": {
-        "fill-range": "^2.1.0"
-      },
-      "dependencies": {
-        "fill-range": {
-          "version": "2.2.4",
-          "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz",
-          "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==",
-          "dev": true,
-          "requires": {
-            "is-number": "^2.1.0",
-            "isobject": "^2.0.0",
-            "randomatic": "^3.0.0",
-            "repeat-element": "^1.1.2",
-            "repeat-string": "^1.5.2"
-          }
-        },
-        "is-number": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
-          "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=",
-          "dev": true,
-          "requires": {
-            "kind-of": "^3.0.2"
-          }
-        },
-        "isarray": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
-          "dev": true
-        },
-        "isobject": {
-          "version": "2.1.0",
-          "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
-          "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
-          "dev": true,
-          "requires": {
-            "isarray": "1.0.0"
-          }
-        },
-        "kind-of": {
-          "version": "3.2.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "^1.1.5"
-          }
-        }
-      }
-    },
     "expand-tilde": {
     "expand-tilde": {
       "version": "2.0.2",
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
       "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
@@ -1568,12 +1375,6 @@
         "object-assign": "^4.0.1"
         "object-assign": "^4.0.1"
       }
       }
     },
     },
-    "filename-regex": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
-      "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=",
-      "dev": true
-    },
     "fill-range": {
     "fill-range": {
       "version": "4.0.0",
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
       "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
@@ -1656,15 +1457,6 @@
       "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
       "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
       "dev": true
       "dev": true
     },
     },
-    "for-own": {
-      "version": "0.1.5",
-      "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
-      "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=",
-      "dev": true,
-      "requires": {
-        "for-in": "^1.0.1"
-      }
-    },
     "forever-agent": {
     "forever-agent": {
       "version": "0.6.1",
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
       "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
@@ -2292,59 +2084,6 @@
         "path-is-absolute": "^1.0.0"
         "path-is-absolute": "^1.0.0"
       }
       }
     },
     },
-    "glob-base": {
-      "version": "0.3.0",
-      "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
-      "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=",
-      "dev": true,
-      "requires": {
-        "glob-parent": "^2.0.0",
-        "is-glob": "^2.0.0"
-      },
-      "dependencies": {
-        "is-extglob": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
-          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
-          "dev": true
-        },
-        "is-glob": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
-          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^1.0.0"
-          }
-        }
-      }
-    },
-    "glob-parent": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
-      "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=",
-      "dev": true,
-      "requires": {
-        "is-glob": "^2.0.0"
-      },
-      "dependencies": {
-        "is-extglob": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
-          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
-          "dev": true
-        },
-        "is-glob": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
-          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^1.0.0"
-          }
-        }
-      }
-    },
     "global-modules": {
     "global-modules": {
       "version": "1.0.0",
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
       "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
@@ -2714,15 +2453,6 @@
       "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
       "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
       "dev": true
       "dev": true
     },
     },
-    "is-binary-path": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
-      "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
-      "dev": true,
-      "requires": {
-        "binary-extensions": "^1.0.0"
-      }
-    },
     "is-buffer": {
     "is-buffer": {
       "version": "1.1.6",
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
       "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
@@ -2777,21 +2507,6 @@
         }
         }
       }
       }
     },
     },
-    "is-dotfile": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
-      "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=",
-      "dev": true
-    },
-    "is-equal-shallow": {
-      "version": "0.1.3",
-      "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
-      "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=",
-      "dev": true,
-      "requires": {
-        "is-primitive": "^2.0.0"
-      }
-    },
     "is-extendable": {
     "is-extendable": {
       "version": "0.1.1",
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
       "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
@@ -2881,18 +2596,6 @@
         "isobject": "^3.0.1"
         "isobject": "^3.0.1"
       }
       }
     },
     },
-    "is-posix-bracket": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
-      "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=",
-      "dev": true
-    },
-    "is-primitive": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
-      "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=",
-      "dev": true
-    },
     "is-promise": {
     "is-promise": {
       "version": "2.1.0",
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
       "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
@@ -3172,12 +2875,6 @@
         "minimatch": "^3.0.2"
         "minimatch": "^3.0.2"
       }
       }
     },
     },
-    "math-random": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz",
-      "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=",
-      "dev": true
-    },
     "mem": {
     "mem": {
       "version": "1.1.0",
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
       "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
@@ -3485,16 +3182,6 @@
         "isobject": "^3.0.0"
         "isobject": "^3.0.0"
       }
       }
     },
     },
-    "object.omit": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
-      "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=",
-      "dev": true,
-      "requires": {
-        "for-own": "^0.1.4",
-        "is-extendable": "^0.1.1"
-      }
-    },
     "object.pick": {
     "object.pick": {
       "version": "1.3.0",
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
       "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
@@ -3613,35 +3300,6 @@
       "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==",
       "integrity": "sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ==",
       "dev": true
       "dev": true
     },
     },
-    "parse-glob": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
-      "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=",
-      "dev": true,
-      "requires": {
-        "glob-base": "^0.3.0",
-        "is-dotfile": "^1.0.0",
-        "is-extglob": "^1.0.0",
-        "is-glob": "^2.0.0"
-      },
-      "dependencies": {
-        "is-extglob": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
-          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
-          "dev": true
-        },
-        "is-glob": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
-          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^1.0.0"
-          }
-        }
-      }
-    },
     "parse-json": {
     "parse-json": {
       "version": "4.0.0",
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
       "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
@@ -3775,12 +3433,6 @@
       "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
       "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
       "dev": true
       "dev": true
     },
     },
-    "preserve": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
-      "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=",
-      "dev": true
-    },
     "pretty-bytes": {
     "pretty-bytes": {
       "version": "1.0.4",
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz",
       "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-1.0.4.tgz",
@@ -3852,25 +3504,6 @@
         "walk-sync": "0.3.2"
         "walk-sync": "0.3.2"
       }
       }
     },
     },
-    "randomatic": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.0.tgz",
-      "integrity": "sha512-KnGPVE0lo2WoXxIZ7cPR8YBpiol4gsSuOwDSg410oHh80ZMp5EiypNqL2K4Z77vJn6lB5rap7IkAmcUlalcnBQ==",
-      "dev": true,
-      "requires": {
-        "is-number": "^4.0.0",
-        "kind-of": "^6.0.0",
-        "math-random": "^1.0.1"
-      },
-      "dependencies": {
-        "is-number": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
-          "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==",
-          "dev": true
-        }
-      }
-    },
     "rc": {
     "rc": {
       "version": "1.2.8",
       "version": "1.2.8",
       "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
       "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
@@ -3948,50 +3581,6 @@
         "string_decoder": "~0.10.x"
         "string_decoder": "~0.10.x"
       }
       }
     },
     },
-    "readdirp": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz",
-      "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=",
-      "dev": true,
-      "requires": {
-        "graceful-fs": "^4.1.2",
-        "minimatch": "^3.0.2",
-        "readable-stream": "^2.0.2",
-        "set-immediate-shim": "^1.0.1"
-      },
-      "dependencies": {
-        "isarray": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-          "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
-          "dev": true
-        },
-        "readable-stream": {
-          "version": "2.3.6",
-          "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz",
-          "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==",
-          "dev": true,
-          "requires": {
-            "core-util-is": "~1.0.0",
-            "inherits": "~2.0.3",
-            "isarray": "~1.0.0",
-            "process-nextick-args": "~2.0.0",
-            "safe-buffer": "~5.1.1",
-            "string_decoder": "~1.1.1",
-            "util-deprecate": "~1.0.1"
-          }
-        },
-        "string_decoder": {
-          "version": "1.1.1",
-          "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-          "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-          "dev": true,
-          "requires": {
-            "safe-buffer": "~5.1.0"
-          }
-        }
-      }
-    },
     "redent": {
     "redent": {
       "version": "1.0.0",
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
       "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
@@ -4002,15 +3591,6 @@
         "strip-indent": "^1.0.1"
         "strip-indent": "^1.0.1"
       }
       }
     },
     },
-    "regex-cache": {
-      "version": "0.4.4",
-      "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
-      "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
-      "dev": true,
-      "requires": {
-        "is-equal-shallow": "^0.1.3"
-      }
-    },
     "regex-not": {
     "regex-not": {
       "version": "1.0.2",
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
       "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
@@ -4100,12 +3680,6 @@
       "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
       "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
       "dev": true
       "dev": true
     },
     },
-    "require-relative": {
-      "version": "0.8.7",
-      "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz",
-      "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=",
-      "dev": true
-    },
     "require-uncached": {
     "require-uncached": {
       "version": "1.0.3",
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
       "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
@@ -4179,127 +3753,15 @@
       }
       }
     },
     },
     "rollup": {
     "rollup": {
-      "version": "0.65.0",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.65.0.tgz",
-      "integrity": "sha512-en95i7zwW5IiWay6DR/6QV8TxO2LvWuCjHYDcgP96oVG/gPnWWzsxNViObhoJUs17bAj2RgB67WuBuGmysZZcw==",
+      "version": "0.65.2",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.65.2.tgz",
+      "integrity": "sha512-BbXOrpxVbx0MpElI6vVLR2B6vnWHvYU/QAMw3GcEXvs601bvgrozuaW30cnvt43B96a6DeoYA0i9T5THanN+Rw==",
       "dev": true,
       "dev": true,
       "requires": {
       "requires": {
         "@types/estree": "0.0.39",
         "@types/estree": "0.0.39",
         "@types/node": "*"
         "@types/node": "*"
       }
       }
     },
     },
-    "rollup-pluginutils": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.3.1.tgz",
-      "integrity": "sha512-JZS8aJMHEHhqmY2QVPMXwKP6lsD1ShkrcGYjhAIvqKKdXQyPHw/9NF0tl3On/xOJ4ACkxfeG7AF+chfCN1NpBg==",
-      "dev": true,
-      "requires": {
-        "estree-walker": "^0.5.2",
-        "micromatch": "^2.3.11"
-      },
-      "dependencies": {
-        "arr-diff": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
-          "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=",
-          "dev": true,
-          "requires": {
-            "arr-flatten": "^1.0.1"
-          }
-        },
-        "array-unique": {
-          "version": "0.2.1",
-          "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
-          "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=",
-          "dev": true
-        },
-        "braces": {
-          "version": "1.8.5",
-          "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
-          "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=",
-          "dev": true,
-          "requires": {
-            "expand-range": "^1.8.1",
-            "preserve": "^0.2.0",
-            "repeat-element": "^1.1.2"
-          }
-        },
-        "expand-brackets": {
-          "version": "0.1.5",
-          "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
-          "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=",
-          "dev": true,
-          "requires": {
-            "is-posix-bracket": "^0.1.0"
-          }
-        },
-        "extglob": {
-          "version": "0.3.2",
-          "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
-          "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^1.0.0"
-          }
-        },
-        "is-extglob": {
-          "version": "1.0.0",
-          "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
-          "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=",
-          "dev": true
-        },
-        "is-glob": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
-          "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=",
-          "dev": true,
-          "requires": {
-            "is-extglob": "^1.0.0"
-          }
-        },
-        "kind-of": {
-          "version": "3.2.2",
-          "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
-          "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
-          "dev": true,
-          "requires": {
-            "is-buffer": "^1.1.5"
-          }
-        },
-        "micromatch": {
-          "version": "2.3.11",
-          "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
-          "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=",
-          "dev": true,
-          "requires": {
-            "arr-diff": "^2.0.0",
-            "array-unique": "^0.2.1",
-            "braces": "^1.8.2",
-            "expand-brackets": "^0.1.4",
-            "extglob": "^0.3.1",
-            "filename-regex": "^2.0.0",
-            "is-extglob": "^1.0.0",
-            "is-glob": "^2.0.1",
-            "kind-of": "^3.0.2",
-            "normalize-path": "^2.0.1",
-            "object.omit": "^2.0.0",
-            "parse-glob": "^3.0.4",
-            "regex-cache": "^0.4.2"
-          }
-        }
-      }
-    },
-    "rollup-watch": {
-      "version": "4.3.1",
-      "resolved": "https://registry.npmjs.org/rollup-watch/-/rollup-watch-4.3.1.tgz",
-      "integrity": "sha1-WqHq6reHrd82iQXRArOdb8XOSos=",
-      "dev": true,
-      "requires": {
-        "chokidar": "^1.7.0",
-        "require-relative": "0.8.7",
-        "rollup-pluginutils": "^2.0.1"
-      }
-    },
     "rsvp": {
     "rsvp": {
       "version": "3.6.2",
       "version": "3.6.2",
       "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz",
       "resolved": "https://registry.npmjs.org/rsvp/-/rsvp-3.6.2.tgz",
@@ -4374,12 +3836,6 @@
       "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
       "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
       "dev": true
       "dev": true
     },
     },
-    "set-immediate-shim": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
-      "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=",
-      "dev": true
-    },
     "set-value": {
     "set-value": {
       "version": "2.0.0",
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",
       "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz",

+ 1 - 1
package.json

@@ -57,7 +57,7 @@
     "google-closure-compiler": "20180805.0.0",
     "google-closure-compiler": "20180805.0.0",
     "http-server": "^0.11.1",
     "http-server": "^0.11.1",
     "qunit": "^2.6.2",
     "qunit": "^2.6.2",
-    "rollup": "^0.65.0"
+    "rollup": "^0.65.2"
   },
   },
   "jspm": {
   "jspm": {
     "files": [
     "files": [

+ 12 - 0
src/Three.Legacy.js

@@ -45,6 +45,7 @@ import { AudioLoader } from './loaders/AudioLoader.js';
 import { CubeTextureLoader } from './loaders/CubeTextureLoader.js';
 import { CubeTextureLoader } from './loaders/CubeTextureLoader.js';
 import { DataTextureLoader } from './loaders/DataTextureLoader.js';
 import { DataTextureLoader } from './loaders/DataTextureLoader.js';
 import { JSONLoader } from './loaders/JSONLoader.js';
 import { JSONLoader } from './loaders/JSONLoader.js';
+import { ObjectLoader } from './loaders/ObjectLoader.js';
 import { TextureLoader } from './loaders/TextureLoader.js';
 import { TextureLoader } from './loaders/TextureLoader.js';
 import { Material } from './materials/Material.js';
 import { Material } from './materials/Material.js';
 import { LineBasicMaterial } from './materials/LineBasicMaterial.js';
 import { LineBasicMaterial } from './materials/LineBasicMaterial.js';
@@ -447,6 +448,17 @@ Object.assign( JSONLoader.prototype, {
 
 
 } );
 } );
 
 
+Object.assign( ObjectLoader.prototype, {
+
+	setTexturePath: function ( value ) {
+
+		console.warn( 'THREE.ObjectLoader: .setTexturePath() has been renamed to .setResourcePath().' );
+		return this.setResourcePath( value );
+
+	}
+
+} );
+
 //
 //
 
 
 Object.assign( Box2.prototype, {
 Object.assign( Box2.prototype, {

+ 61 - 1
src/cameras/ArrayCamera.js

@@ -3,6 +3,7 @@
  */
  */
 
 
 import { PerspectiveCamera } from './PerspectiveCamera.js';
 import { PerspectiveCamera } from './PerspectiveCamera.js';
+import { Vector3 } from '../math/Vector3.js';
 
 
 function ArrayCamera( array ) {
 function ArrayCamera( array ) {
 
 
@@ -16,7 +17,66 @@ ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototyp
 
 
 	constructor: ArrayCamera,
 	constructor: ArrayCamera,
 
 
-	isArrayCamera: true
+	isArrayCamera: true,
+
+	/**
+	 * Assumes 2 cameras that are perpendicular and share an X-axis, and that
+	 * the cameras' projection and world matrices have already been set.
+	 * And that near and far planes are identical for both cameras.
+	 */
+	setProjectionFromUnion: function () {
+		var cameraLPos = new Vector3();
+		var cameraRPos = new Vector3();
+
+		return function () {
+			cameraLPos.setFromMatrixPosition( this.cameras[ 0 ].matrixWorld );
+			cameraRPos.setFromMatrixPosition( this.cameras[ 1 ].matrixWorld );
+
+			var ipd = cameraLPos.distanceTo( cameraRPos );
+
+			var projL = this.cameras[ 0 ].projectionMatrix;
+			var projR = this.cameras[ 1 ].projectionMatrix;
+
+			// VR systems will have identical far and near planes, and
+			// most likely identical top and bottom frustum extents.
+			// via: https://computergraphics.stackexchange.com/a/4765
+			var near = projL[ 14 ] / ( projL[ 10 ] - 1 );
+			var far = projL[ 14 ] / ( projL[ 10 ] + 1 );
+
+			var leftFovL = ( projL[ 8 ] - 1 ) / projL[ 0 ];
+			var rightFovR = ( projR[ 8 ] + 1 ) / projR[ 0 ];
+			var leftL = leftFovL * near;
+			var rightR = rightFovR * near;
+			var topL = near * ( projL[ 9 ] + 1 ) / projL[ 5 ];
+			var topR = near * ( projR[ 9 ] + 1 ) / projR[ 5 ];
+			var bottomL = near * ( projL[ 9 ] - 1 ) / projL[ 5 ];
+			var bottomR = near * ( projR[ 9 ] - 1 ) / projR[ 5 ];
+
+			// Calculate the new camera's position offset from the
+			// left camera.
+			var zOffset = ipd / (leftFovL + rightFovR);
+			var xOffset = zOffset * leftFovL;
+
+			// TODO: Better way to apply this offset?
+			this.cameras[ 0 ].matrixWorld.decompose( this.position, this.quaternion, this.scale );
+			this.translateX(xOffset);
+			this.translateZ(-zOffset);
+			this.matrixWorld.compose( this.position, this.quaternion, this.scale );
+			this.matrixWorldInverse.getInverse(this.matrixWorld);
+
+			// Find the union of the frustum values of the cameras and scale
+			// the values so that the near plane's position does not change in world space,
+			// although must now be relative to the new union camera.
+			var near2 = near + zOffset;
+			var far2 = far + zOffset;
+			var left = leftL - xOffset;
+			var right = rightR + (ipd - xOffset)
+			var top = Math.max( topL, topR );
+			var bottom = Math.min( bottomL, bottomR );
+
+			this.projectionMatrix.makePerspective( left, right, top, bottom, near2, far2 );
+		}
+	}(),
 
 
 } );
 } );
 
 

+ 1 - 1
src/constants.js

@@ -1,4 +1,4 @@
-export var REVISION = '97';
+export var REVISION = '98dev';
 export var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };
 export var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };
 export var CullFaceNone = 0;
 export var CullFaceNone = 0;
 export var CullFaceBack = 1;
 export var CullFaceBack = 1;

+ 4 - 0
src/core/Object3D.js

@@ -53,18 +53,22 @@ function Object3D() {
 
 
 	Object.defineProperties( this, {
 	Object.defineProperties( this, {
 		position: {
 		position: {
+			configurable: true,
 			enumerable: true,
 			enumerable: true,
 			value: position
 			value: position
 		},
 		},
 		rotation: {
 		rotation: {
+			configurable: true,
 			enumerable: true,
 			enumerable: true,
 			value: rotation
 			value: rotation
 		},
 		},
 		quaternion: {
 		quaternion: {
+			configurable: true,
 			enumerable: true,
 			enumerable: true,
 			value: quaternion
 			value: quaternion
 		},
 		},
 		scale: {
 		scale: {
+			configurable: true,
 			enumerable: true,
 			enumerable: true,
 			value: scale
 			value: scale
 		},
 		},

+ 5 - 1
src/extras/ImageUtils.js

@@ -10,7 +10,11 @@ var ImageUtils = {
 
 
 		var canvas;
 		var canvas;
 
 
-		if ( image instanceof HTMLCanvasElement ) {
+		if ( typeof HTMLCanvasElement == 'undefined' ) {
+
+			return image.src;
+
+		} else if ( image instanceof HTMLCanvasElement ) {
 
 
 			canvas = image;
 			canvas = image;
 
 

+ 4 - 4
src/loaders/FileLoader.js

@@ -70,9 +70,9 @@ Object.assign( FileLoader.prototype, {
 			var isBase64 = !! dataUriRegexResult[ 2 ];
 			var isBase64 = !! dataUriRegexResult[ 2 ];
 			var data = dataUriRegexResult[ 3 ];
 			var data = dataUriRegexResult[ 3 ];
 
 
-			data = window.decodeURIComponent( data );
+			data = decodeURIComponent( data );
 
 
-			if ( isBase64 ) data = window.atob( data );
+			if ( isBase64 ) data = atob( data );
 
 
 			try {
 			try {
 
 
@@ -126,7 +126,7 @@ Object.assign( FileLoader.prototype, {
 				}
 				}
 
 
 				// Wait for next browser tick like standard XMLHttpRequest event dispatching does
 				// Wait for next browser tick like standard XMLHttpRequest event dispatching does
-				window.setTimeout( function () {
+				setTimeout( function () {
 
 
 					if ( onLoad ) onLoad( response );
 					if ( onLoad ) onLoad( response );
 
 
@@ -137,7 +137,7 @@ Object.assign( FileLoader.prototype, {
 			} catch ( error ) {
 			} catch ( error ) {
 
 
 				// Wait for next browser tick like standard XMLHttpRequest event dispatching does
 				// Wait for next browser tick like standard XMLHttpRequest event dispatching does
-				window.setTimeout( function () {
+				setTimeout( function () {
 
 
 					if ( onError ) onError( error );
 					if ( onError ) onError( error );
 
 

+ 18 - 12
src/loaders/ObjectLoader.js

@@ -48,6 +48,7 @@ import { ImageLoader } from './ImageLoader.js';
 import { LoadingManager, DefaultLoadingManager } from './LoadingManager.js';
 import { LoadingManager, DefaultLoadingManager } from './LoadingManager.js';
 import { AnimationClip } from '../animation/AnimationClip.js';
 import { AnimationClip } from '../animation/AnimationClip.js';
 import { MaterialLoader } from './MaterialLoader.js';
 import { MaterialLoader } from './MaterialLoader.js';
+import { LoaderUtils } from './LoaderUtils.js';
 import { BufferGeometryLoader } from './BufferGeometryLoader.js';
 import { BufferGeometryLoader } from './BufferGeometryLoader.js';
 import { JSONLoader } from './JSONLoader.js';
 import { JSONLoader } from './JSONLoader.js';
 import { FileLoader } from './FileLoader.js';
 import { FileLoader } from './FileLoader.js';
@@ -61,7 +62,7 @@ import * as Curves from '../extras/curves/Curves.js';
 function ObjectLoader( manager ) {
 function ObjectLoader( manager ) {
 
 
 	this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
 	this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager;
-	this.texturePath = '';
+	this.resourcePath = '';
 
 
 }
 }
 
 
@@ -71,15 +72,13 @@ Object.assign( ObjectLoader.prototype, {
 
 
 	load: function ( url, onLoad, onProgress, onError ) {
 	load: function ( url, onLoad, onProgress, onError ) {
 
 
-		if ( this.texturePath === '' ) {
-
-			this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 );
-
-		}
-
 		var scope = this;
 		var scope = this;
 
 
+		var path = ( this.path === undefined ) ? LoaderUtils.extractUrlBase( url ) : this.path;
+		this.resourcePath = this.resourcePath || path;
+
 		var loader = new FileLoader( scope.manager );
 		var loader = new FileLoader( scope.manager );
+		loader.setPath( this.path );
 		loader.load( url, function ( text ) {
 		loader.load( url, function ( text ) {
 
 
 			var json = null;
 			var json = null;
@@ -113,9 +112,16 @@ Object.assign( ObjectLoader.prototype, {
 
 
 	},
 	},
 
 
-	setTexturePath: function ( value ) {
+	setPath: function ( value ) {
+
+		this.path = value;
+		return this;
+
+	},
+
+	setResourcePath: function ( value ) {
 
 
-		this.texturePath = value;
+		this.resourcePath = value;
 		return this;
 		return this;
 
 
 	},
 	},
@@ -418,7 +424,7 @@ Object.assign( ObjectLoader.prototype, {
 
 
 					case 'Geometry':
 					case 'Geometry':
 
 
-						geometry = geometryLoader.parse( data, this.texturePath ).geometry;
+						geometry = geometryLoader.parse( data, this.resourcePath ).geometry;
 
 
 						break;
 						break;
 
 
@@ -550,7 +556,7 @@ Object.assign( ObjectLoader.prototype, {
 
 
 						var currentUrl = url[ j ];
 						var currentUrl = url[ j ];
 
 
-						var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( currentUrl ) ? currentUrl : scope.texturePath + currentUrl;
+						var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( currentUrl ) ? currentUrl : scope.resourcePath + currentUrl;
 
 
 						images[ image.uuid ].push( loadImage( path ) );
 						images[ image.uuid ].push( loadImage( path ) );
 
 
@@ -560,7 +566,7 @@ Object.assign( ObjectLoader.prototype, {
 
 
 					// load single image
 					// load single image
 
 
-					var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url;
+					var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.resourcePath + image.url;
 
 
 					images[ image.uuid ] = loadImage( path );
 					images[ image.uuid ] = loadImage( path );
 
 

+ 1 - 1
src/renderers/shaders/ShaderChunk/bsdfs.glsl

@@ -19,7 +19,7 @@ float punctualLightIntensityToIrradianceFactor( const in float lightDistance, co
 
 
 #else
 #else
 
 
-	if( cutoffDistance > 0.0 ) {
+	if( cutoffDistance > 0.0 && decayExponent > 0.0 ) {
 
 
 		return pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );
 		return pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );
 
 

+ 1 - 7
src/renderers/webvr/WebVRManager.js

@@ -290,9 +290,6 @@ function WebVRManager( renderer ) {
 		cameraL.far = camera.far;
 		cameraL.far = camera.far;
 		cameraR.far = camera.far;
 		cameraR.far = camera.far;
 
 
-		cameraVR.matrixWorld.copy( camera.matrixWorld );
-		cameraVR.matrixWorldInverse.copy( camera.matrixWorldInverse );
-
 		cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix );
 		cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix );
 		cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix );
 		cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix );
 
 
@@ -326,10 +323,7 @@ function WebVRManager( renderer ) {
 		cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix );
 		cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix );
 		cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix );
 		cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix );
 
 
-		// HACK (mrdoob)
-		// https://github.com/w3c/webvr/issues/203
-
-		cameraVR.projectionMatrix.copy( cameraL.projectionMatrix );
+		cameraVR.setProjectionFromUnion();
 
 
 		//
 		//
 
 

+ 2 - 7
src/renderers/webvr/WebXRManager.js

@@ -161,8 +161,6 @@ function WebXRManager( renderer ) {
 			var parent = camera.parent;
 			var parent = camera.parent;
 			var cameras = cameraVR.cameras;
 			var cameras = cameraVR.cameras;
 
 
-			// apply camera.parent to cameraVR
-
 			updateCamera( cameraVR, parent );
 			updateCamera( cameraVR, parent );
 
 
 			for ( var i = 0; i < cameras.length; i ++ ) {
 			for ( var i = 0; i < cameras.length; i ++ ) {
@@ -183,6 +181,8 @@ function WebXRManager( renderer ) {
 
 
 			}
 			}
 
 
+			cameraVR.setProjectionFromUnion();
+
 			return cameraVR;
 			return cameraVR;
 
 
 		}
 		}
@@ -221,11 +221,6 @@ function WebXRManager( renderer ) {
 
 
 					cameraVR.matrix.copy( camera.matrix );
 					cameraVR.matrix.copy( camera.matrix );
 
 
-					// HACK (mrdoob)
-					// https://github.com/w3c/webvr/issues/203
-
-					cameraVR.projectionMatrix.copy( camera.projectionMatrix );
-
 				}
 				}
 
 
 			}
 			}

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