Browse Source

Merge pull request #12 from mrdoob/dev

Update
Temdog007 6 years ago
parent
commit
fa398a1cb7
58 changed files with 1301 additions and 728 deletions
  1. 50 37
      build/three.js
  2. 68 293
      build/three.min.js
  3. 50 37
      build/three.module.js
  4. 1 1
      docs/api/en/renderers/WebGLRenderer.html
  5. 53 11
      docs/index.html
  6. 2 2
      docs/manual/en/introduction/Import-via-modules.html
  7. 15 13
      docs/manual/en/introduction/Useful-links.html
  8. 20 12
      docs/manual/zh/introduction/Useful-links.html
  9. 89 38
      docs/page.css
  10. 2 2
      docs/prettify/threejs.css
  11. 5 4
      editor/manifest.json
  12. 2 2
      examples/css3d_panorama_deviceorientation.html
  13. 1 0
      examples/files.js
  14. 66 24
      examples/index.html
  15. 6 1
      examples/js/exporters/GLTFExporter.js
  16. 343 44
      examples/js/loaders/3MFLoader.js
  17. 4 2
      examples/js/loaders/GLTFLoader.js
  18. 34 7
      examples/js/postprocessing/EffectComposer.js
  19. 2 3
      examples/misc_controls_fly.html
  20. BIN
      examples/models/3mf/truck.3mf
  21. BIN
      examples/models/kmz/Box.kmz
  22. BIN
      examples/textures/memorial.exr
  23. BIN
      examples/textures/memorial.hdr
  24. 0 10
      examples/textures/miranda_uncropped.hdr
  25. 5 5
      examples/webgl_buffergeometry_lines.html
  26. 5 5
      examples/webgl_buffergeometry_lines_indexed.html
  27. 6 6
      examples/webgl_custom_attributes_lines.html
  28. 158 0
      examples/webgl_loader_3mf_materials.html
  29. 6 5
      examples/webgl_loader_texture_exr.html
  30. 6 5
      examples/webgl_loader_texture_hdr.html
  31. 1 1
      examples/webgl_materials_video.html
  32. 6 7
      examples/webgl_points_dynamic.html
  33. 1 5
      examples/webgl_postprocessing_backgrounds.html
  34. 17 2
      examples/webgl_postprocessing_masking.html
  35. 1 5
      examples/webgl_postprocessing_smaa.html
  36. 4 4
      examples/webgl_postprocessing_sobel.html
  37. 1 5
      examples/webgl_postprocessing_ssaa.html
  38. 2 5
      examples/webgl_postprocessing_ssaa_unbiased.html
  39. 8 11
      examples/webgl_postprocessing_ssao.html
  40. 1 5
      examples/webgl_postprocessing_taa.html
  41. 0 1
      examples/webgl_postprocessing_unreal_bloom.html
  42. 2 4
      examples/webgl_postprocessing_unreal_bloom_selective.html
  43. 2 3
      examples/webgl_shader_lava.html
  44. 4 0
      files/ic_close_black_24dp.svg
  45. 4 0
      files/ic_code_black_24dp.svg
  46. 15 0
      files/ic_github_black_24dp.svg
  47. 165 85
      files/main.css
  48. 17 3
      src/animation/AnimationAction.js
  49. 11 0
      src/core/BufferAttribute.js
  50. 2 12
      src/core/BufferGeometry.js
  51. 12 0
      src/core/InstancedBufferAttribute.js
  52. 1 0
      src/geometries/ExtrudeGeometry.d.ts
  53. 3 0
      src/geometries/TextGeometry.d.ts
  54. 1 0
      src/materials/Material.d.ts
  55. 1 1
      src/renderers/WebGLRenderer.js
  56. 9 0
      src/renderers/webgl/WebGLAnimation.d.ts
  57. 9 0
      src/renderers/webgl/WebGLAttributes.d.ts
  58. 2 0
      src/renderers/webvr/WebVRManager.js

+ 50 - 37
build/three.js

@@ -21971,6 +21971,7 @@
 
 
 	function WebVRManager( renderer ) {
 	function WebVRManager( renderer ) {
 
 
+		var renderWidth, renderHeight;
 		var scope = this;
 		var scope = this;
 
 
 		var device = null;
 		var device = null;
@@ -21998,11 +21999,11 @@
 		var tempPosition = new Vector3();
 		var tempPosition = new Vector3();
 
 
 		var cameraL = new PerspectiveCamera();
 		var cameraL = new PerspectiveCamera();
-		cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 );
+		cameraL.viewport = new Vector4();
 		cameraL.layers.enable( 1 );
 		cameraL.layers.enable( 1 );
 
 
 		var cameraR = new PerspectiveCamera();
 		var cameraR = new PerspectiveCamera();
-		cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 );
+		cameraR.viewport = new Vector4();
 		cameraR.layers.enable( 2 );
 		cameraR.layers.enable( 2 );
 
 
 		var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
 		var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
@@ -22024,14 +22025,17 @@
 			if ( isPresenting() ) {
 			if ( isPresenting() ) {
 
 
 				var eyeParameters = device.getEyeParameters( 'left' );
 				var eyeParameters = device.getEyeParameters( 'left' );
-				var renderWidth = eyeParameters.renderWidth * framebufferScaleFactor;
-				var renderHeight = eyeParameters.renderHeight * framebufferScaleFactor;
+				renderWidth = eyeParameters.renderWidth * framebufferScaleFactor;
+				renderHeight = eyeParameters.renderHeight * framebufferScaleFactor;
 
 
 				currentPixelRatio = renderer.getPixelRatio();
 				currentPixelRatio = renderer.getPixelRatio();
 				renderer.getSize( currentSize );
 				renderer.getSize( currentSize );
 
 
 				renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 );
 				renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 );
 
 
+				cameraL.viewport.set( 0, 0, renderWidth, renderHeight );
+				cameraR.viewport.set( renderWidth, 0, renderWidth, renderHeight );
+
 				animation.start();
 				animation.start();
 
 
 			} else {
 			} else {
@@ -22132,6 +22136,16 @@
 
 
 		}
 		}
 
 
+		function updateViewportFromBounds( viewport, bounds ) {
+
+			if ( bounds !== null && bounds.length === 4 ) {
+
+				viewport.set( bounds[ 0 ] * renderWidth, bounds[ 1 ] * renderHeight, bounds[ 2 ] * renderWidth, bounds[ 3 ] * renderHeight );
+
+			}
+
+		}
+
 		//
 		//
 
 
 		this.enabled = false;
 		this.enabled = false;
@@ -22299,17 +22313,8 @@
 
 
 				var layer = layers[ 0 ];
 				var layer = layers[ 0 ];
 
 
-				if ( layer.leftBounds !== null && layer.leftBounds.length === 4 ) {
-
-					cameraL.bounds.fromArray( layer.leftBounds );
-
-				}
-
-				if ( layer.rightBounds !== null && layer.rightBounds.length === 4 ) {
-
-					cameraR.bounds.fromArray( layer.rightBounds );
-
-				}
+				updateViewportFromBounds( cameraL.viewport, layer.leftBounds );
+				updateViewportFromBounds( cameraR.viewport, layer.rightBounds );
 
 
 			}
 			}
 
 
@@ -22703,7 +22708,7 @@
 			 * Enables error checking and reporting when shader programs are being compiled
 			 * Enables error checking and reporting when shader programs are being compiled
 			 * @type {boolean}
 			 * @type {boolean}
 			 */
 			 */
-			checkShaderErrors: false
+			checkShaderErrors: true
 		};
 		};
 
 
 		// clearing
 		// clearing
@@ -23998,22 +24003,7 @@
 
 
 						if ( object.layers.test( camera2.layers ) ) {
 						if ( object.layers.test( camera2.layers ) ) {
 
 
-							if ( 'viewport' in camera2 ) { // XR
-
-								state.viewport( _currentViewport.copy( camera2.viewport ) );
-
-							} else {
-
-								var bounds = camera2.bounds;
-
-								var x = bounds.x * _width;
-								var y = bounds.y * _height;
-								var width = bounds.z * _width;
-								var height = bounds.w * _height;
-
-								state.viewport( _currentViewport.set( x, y, width, height ).multiplyScalar( _pixelRatio ) );
-
-							}
+							state.viewport( _currentViewport.copy( camera2.viewport ) );
 
 
 							currentRenderState.setupLights( camera2 );
 							currentRenderState.setupLights( camera2 );
 
 
@@ -38035,8 +38025,17 @@
 
 
 			}
 			}
 
 
-			// Merges multi-byte utf-8 characters.
-			return decodeURIComponent( escape( s ) );
+			try {
+
+				// merges multi-byte utf-8 characters.
+
+				return decodeURIComponent( escape( s ) );
+
+			} catch ( e ) { // see #16358
+
+				return s;
+
+			}
 
 
 		},
 		},
 
 
@@ -43244,11 +43243,19 @@
 
 
 						time = 0;
 						time = 0;
 
 
-					} else break handle_stop;
+					} else {
+
+						this.time = time;
+
+						break handle_stop;
+
+					}
 
 
 					if ( this.clampWhenFinished ) this.paused = true;
 					if ( this.clampWhenFinished ) this.paused = true;
 					else this.enabled = false;
 					else this.enabled = false;
 
 
+					this.time = time;
+
 					this._mixer.dispatchEvent( {
 					this._mixer.dispatchEvent( {
 						type: 'finished', action: this,
 						type: 'finished', action: this,
 						direction: deltaTime < 0 ? - 1 : 1
 						direction: deltaTime < 0 ? - 1 : 1
@@ -43300,6 +43307,8 @@
 
 
 						time = deltaTime > 0 ? duration : 0;
 						time = deltaTime > 0 ? duration : 0;
 
 
+						this.time = time;
+
 						this._mixer.dispatchEvent( {
 						this._mixer.dispatchEvent( {
 							type: 'finished', action: this,
 							type: 'finished', action: this,
 							direction: deltaTime > 0 ? 1 : - 1
 							direction: deltaTime > 0 ? 1 : - 1
@@ -43324,26 +43333,30 @@
 
 
 						this._loopCount = loopCount;
 						this._loopCount = loopCount;
 
 
+						this.time = time;
+
 						this._mixer.dispatchEvent( {
 						this._mixer.dispatchEvent( {
 							type: 'loop', action: this, loopDelta: loopDelta
 							type: 'loop', action: this, loopDelta: loopDelta
 						} );
 						} );
 
 
 					}
 					}
 
 
+				} else {
+
+					this.time = time;
+
 				}
 				}
 
 
 				if ( pingPong && ( loopCount & 1 ) === 1 ) {
 				if ( pingPong && ( loopCount & 1 ) === 1 ) {
 
 
 					// invert time for the "pong round"
 					// invert time for the "pong round"
 
 
-					this.time = time;
 					return duration - time;
 					return duration - time;
 
 
 				}
 				}
 
 
 			}
 			}
 
 
-			this.time = time;
 			return time;
 			return time;
 
 
 		},
 		},

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


+ 50 - 37
build/three.module.js

@@ -21965,6 +21965,7 @@ function setProjectionFromUnion( camera, cameraL, cameraR ) {
 
 
 function WebVRManager( renderer ) {
 function WebVRManager( renderer ) {
 
 
+	var renderWidth, renderHeight;
 	var scope = this;
 	var scope = this;
 
 
 	var device = null;
 	var device = null;
@@ -21992,11 +21993,11 @@ function WebVRManager( renderer ) {
 	var tempPosition = new Vector3();
 	var tempPosition = new Vector3();
 
 
 	var cameraL = new PerspectiveCamera();
 	var cameraL = new PerspectiveCamera();
-	cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 );
+	cameraL.viewport = new Vector4();
 	cameraL.layers.enable( 1 );
 	cameraL.layers.enable( 1 );
 
 
 	var cameraR = new PerspectiveCamera();
 	var cameraR = new PerspectiveCamera();
-	cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 );
+	cameraR.viewport = new Vector4();
 	cameraR.layers.enable( 2 );
 	cameraR.layers.enable( 2 );
 
 
 	var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
 	var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
@@ -22018,14 +22019,17 @@ function WebVRManager( renderer ) {
 		if ( isPresenting() ) {
 		if ( isPresenting() ) {
 
 
 			var eyeParameters = device.getEyeParameters( 'left' );
 			var eyeParameters = device.getEyeParameters( 'left' );
-			var renderWidth = eyeParameters.renderWidth * framebufferScaleFactor;
-			var renderHeight = eyeParameters.renderHeight * framebufferScaleFactor;
+			renderWidth = eyeParameters.renderWidth * framebufferScaleFactor;
+			renderHeight = eyeParameters.renderHeight * framebufferScaleFactor;
 
 
 			currentPixelRatio = renderer.getPixelRatio();
 			currentPixelRatio = renderer.getPixelRatio();
 			renderer.getSize( currentSize );
 			renderer.getSize( currentSize );
 
 
 			renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 );
 			renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 );
 
 
+			cameraL.viewport.set( 0, 0, renderWidth, renderHeight );
+			cameraR.viewport.set( renderWidth, 0, renderWidth, renderHeight );
+
 			animation.start();
 			animation.start();
 
 
 		} else {
 		} else {
@@ -22126,6 +22130,16 @@ function WebVRManager( renderer ) {
 
 
 	}
 	}
 
 
+	function updateViewportFromBounds( viewport, bounds ) {
+
+		if ( bounds !== null && bounds.length === 4 ) {
+
+			viewport.set( bounds[ 0 ] * renderWidth, bounds[ 1 ] * renderHeight, bounds[ 2 ] * renderWidth, bounds[ 3 ] * renderHeight );
+
+		}
+
+	}
+
 	//
 	//
 
 
 	this.enabled = false;
 	this.enabled = false;
@@ -22293,17 +22307,8 @@ function WebVRManager( renderer ) {
 
 
 			var layer = layers[ 0 ];
 			var layer = layers[ 0 ];
 
 
-			if ( layer.leftBounds !== null && layer.leftBounds.length === 4 ) {
-
-				cameraL.bounds.fromArray( layer.leftBounds );
-
-			}
-
-			if ( layer.rightBounds !== null && layer.rightBounds.length === 4 ) {
-
-				cameraR.bounds.fromArray( layer.rightBounds );
-
-			}
+			updateViewportFromBounds( cameraL.viewport, layer.leftBounds );
+			updateViewportFromBounds( cameraR.viewport, layer.rightBounds );
 
 
 		}
 		}
 
 
@@ -22697,7 +22702,7 @@ function WebGLRenderer( parameters ) {
 		 * Enables error checking and reporting when shader programs are being compiled
 		 * Enables error checking and reporting when shader programs are being compiled
 		 * @type {boolean}
 		 * @type {boolean}
 		 */
 		 */
-		checkShaderErrors: false
+		checkShaderErrors: true
 	};
 	};
 
 
 	// clearing
 	// clearing
@@ -23992,22 +23997,7 @@ function WebGLRenderer( parameters ) {
 
 
 					if ( object.layers.test( camera2.layers ) ) {
 					if ( object.layers.test( camera2.layers ) ) {
 
 
-						if ( 'viewport' in camera2 ) { // XR
-
-							state.viewport( _currentViewport.copy( camera2.viewport ) );
-
-						} else {
-
-							var bounds = camera2.bounds;
-
-							var x = bounds.x * _width;
-							var y = bounds.y * _height;
-							var width = bounds.z * _width;
-							var height = bounds.w * _height;
-
-							state.viewport( _currentViewport.set( x, y, width, height ).multiplyScalar( _pixelRatio ) );
-
-						}
+						state.viewport( _currentViewport.copy( camera2.viewport ) );
 
 
 						currentRenderState.setupLights( camera2 );
 						currentRenderState.setupLights( camera2 );
 
 
@@ -38029,8 +38019,17 @@ var LoaderUtils = {
 
 
 		}
 		}
 
 
-		// Merges multi-byte utf-8 characters.
-		return decodeURIComponent( escape( s ) );
+		try {
+
+			// merges multi-byte utf-8 characters.
+
+			return decodeURIComponent( escape( s ) );
+
+		} catch ( e ) { // see #16358
+
+			return s;
+
+		}
 
 
 	},
 	},
 
 
@@ -43238,11 +43237,19 @@ Object.assign( AnimationAction.prototype, {
 
 
 					time = 0;
 					time = 0;
 
 
-				} else break handle_stop;
+				} else {
+
+					this.time = time;
+
+					break handle_stop;
+
+				}
 
 
 				if ( this.clampWhenFinished ) this.paused = true;
 				if ( this.clampWhenFinished ) this.paused = true;
 				else this.enabled = false;
 				else this.enabled = false;
 
 
+				this.time = time;
+
 				this._mixer.dispatchEvent( {
 				this._mixer.dispatchEvent( {
 					type: 'finished', action: this,
 					type: 'finished', action: this,
 					direction: deltaTime < 0 ? - 1 : 1
 					direction: deltaTime < 0 ? - 1 : 1
@@ -43294,6 +43301,8 @@ Object.assign( AnimationAction.prototype, {
 
 
 					time = deltaTime > 0 ? duration : 0;
 					time = deltaTime > 0 ? duration : 0;
 
 
+					this.time = time;
+
 					this._mixer.dispatchEvent( {
 					this._mixer.dispatchEvent( {
 						type: 'finished', action: this,
 						type: 'finished', action: this,
 						direction: deltaTime > 0 ? 1 : - 1
 						direction: deltaTime > 0 ? 1 : - 1
@@ -43318,26 +43327,30 @@ Object.assign( AnimationAction.prototype, {
 
 
 					this._loopCount = loopCount;
 					this._loopCount = loopCount;
 
 
+					this.time = time;
+
 					this._mixer.dispatchEvent( {
 					this._mixer.dispatchEvent( {
 						type: 'loop', action: this, loopDelta: loopDelta
 						type: 'loop', action: this, loopDelta: loopDelta
 					} );
 					} );
 
 
 				}
 				}
 
 
+			} else {
+
+				this.time = time;
+
 			}
 			}
 
 
 			if ( pingPong && ( loopCount & 1 ) === 1 ) {
 			if ( pingPong && ( loopCount & 1 ) === 1 ) {
 
 
 				// invert time for the "pong round"
 				// invert time for the "pong round"
 
 
-				this.time = time;
 				return duration - time;
 				return duration - time;
 
 
 			}
 			}
 
 
 		}
 		}
 
 
-		this.time = time;
 		return time;
 		return time;
 
 
 	},
 	},

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

@@ -425,7 +425,7 @@
 
 
 		<h3>[method:null setAnimationLoop]( [param:Function callback] )</h3>
 		<h3>[method:null setAnimationLoop]( [param:Function callback] )</h3>
 		<p>[page:Function callback] — The function will be called every available frame. If `null` is passed it will stop any already ongoing animation.</p>
 		<p>[page:Function callback] — The function will be called every available frame. If `null` is passed it will stop any already ongoing animation.</p>
-		<p>A build in function that can be used instead of [link:https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame requestAnimationFrame]. For WebVR projects this function must be used.</p>
+		<p>A built in function that can be used instead of [link:https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame requestAnimationFrame]. For WebVR projects this function must be used.</p>
 
 
 		<h3>[method:null setClearAlpha]( [param:Float alpha] )</h3>
 		<h3>[method:null setClearAlpha]( [param:Float alpha] )</h3>
 		<p>Sets the clear alpha. Valid input is a float between *0.0* and *1.0*.</p>
 		<p>Sets the clear alpha. Valid input is a float between *0.0* and *1.0*.</p>

+ 53 - 11
docs/index.html

@@ -10,30 +10,33 @@
 		<script src="../build/three.min.js" async defer></script>
 		<script src="../build/three.min.js" async defer></script>
 	</head>
 	</head>
 	<body>
 	<body>
-
-		<div id="panel" class="collapsed">
+		<div id="panel" class="">
 
 
 			<div id="header">
 			<div id="header">
-
 				<h1><a href="http://threejs.org">three.js</a></h1>
 				<h1><a href="http://threejs.org">three.js</a></h1>
 
 
-				<img id="expandButton" src="../files/ic_menu_black_24dp.svg">
-
 				<div id="sections">
 				<div id="sections">
-					<span class="selected">docs</span> <a href="../examples/">examples</a>
+					<span class="selected">docs</span>
+					<a href="../examples/">examples</a>
 				</div>
 				</div>
 
 
-				<input type="text" id="filter" autocorrect="off" autocapitalize="off" spellcheck="false">
+				<img id="expandButton" src="../files/ic_menu_black_24dp.svg">
+			</div>
+
+			<div id="panelScrim"></div>
+
+			<div id="contentWrapper">
+				<input placeholder="Search" type="text" id="filter" autocorrect="off" autocapitalize="off" spellcheck="false" />
+				<div id="exitSearchButton"></div>
 
 
 				<select id="language">
 				<select id="language">
 					<option value="en">en</option>
 					<option value="en">en</option>
 					<option value="zh">zh</option>
 					<option value="zh">zh</option>
 				</select>
 				</select>
 
 
+				<div id="content"></div>
 			</div>
 			</div>
 
 
-			<div id="content"></div>
-
 		</div>
 		</div>
 
 
 		<iframe name="viewer"></iframe>
 		<iframe name="viewer"></iframe>
@@ -89,6 +92,8 @@
 			var panel = document.getElementById( 'panel' );
 			var panel = document.getElementById( 'panel' );
 			var content = document.getElementById( 'content' );
 			var content = document.getElementById( 'content' );
 			var expandButton = document.getElementById( 'expandButton' );
 			var expandButton = document.getElementById( 'expandButton' );
+			var exitSearchButton = document.getElementById( 'exitSearchButton' );
+			var panelScrim = document.getElementById( 'panelScrim' );
 			var filterInput = document.getElementById( 'filter' );
 			var filterInput = document.getElementById( 'filter' );
 			var iframe = document.querySelector( 'iframe' );
 			var iframe = document.querySelector( 'iframe' );
 
 
@@ -104,12 +109,40 @@
 			expandButton.onclick = function ( event ) {
 			expandButton.onclick = function ( event ) {
 
 
 				event.preventDefault();
 				event.preventDefault();
-				panel.classList.toggle( 'collapsed' );
+				panel.classList.toggle( 'open' );
+
+			};
+
+			panelScrim.onclick = function ( event ) {
+
+				event.preventDefault();
+				panel.classList.toggle( 'open' );
 
 
 			};
 			};
 
 
 
 
 			// Functionality for search/filter input field
 			// Functionality for search/filter input field
+			filterInput.onfocus = function ( event ) {
+
+				panel.classList.add('searchFocused');
+
+			}
+
+			filterInput.onblur = function ( event ) {
+
+				if(filterInput.value === '') {
+					panel.classList.remove('searchFocused');
+				}
+
+			}
+
+			exitSearchButton.onclick = function( event ) {
+
+				filterInput.value = '';
+				updateFilter();
+				panel.classList.remove('searchFocused');
+
+			}
 
 
 			filterInput.oninput = function ( event ) {
 			filterInput.oninput = function ( event ) {
 
 
@@ -139,7 +172,16 @@
 					if ( event.button !== 0 || event.ctrlKey || event.altKey || event.metaKey ) return;
 					if ( event.button !== 0 || event.ctrlKey || event.altKey || event.metaKey ) return;
 
 
 					window.location.hash = pageURL;
 					window.location.hash = pageURL;
-					panel.classList.add( 'collapsed' );
+					panel.classList.remove( 'open' );
+
+
+					content.querySelectorAll( 'a' ).forEach( function ( item ) {
+
+						item.classList.remove( 'selected' );
+
+					} );
+
+					link.classList.add('selected');
 
 
 				} );
 				} );
 
 

+ 2 - 2
docs/manual/en/introduction/Import-via-modules.html

@@ -27,7 +27,7 @@
 
 
 		<h2>Importing the module</h2>
 		<h2>Importing the module</h2>
 
 
-		<p>Assuming that you're bundling your files with a tool such as [link:https://webpack.github.io/ Webpack] or [link:https://github.com/substack/node-browserify Browserify], which allow you to "require('modules') in the browser by bundling up all of your dependencies."</p>
+		<p>Assuming that you're bundling your files with a tool such as [link:https://webpack.github.io/ Webpack] or [link:https://github.com/substack/node-browserify Browserify], which allow you to "require('modules')" in the browser by bundling up all of your dependencies.</p>
 
 
 		<p>
 		<p>
 			You should now be able to import the module into your source files and continue to use it as per normal.
 			You should now be able to import the module into your source files and continue to use it as per normal.
@@ -124,7 +124,7 @@
 		</p>
 		</p>
 		<p>
 		<p>
 			Note: When using code from the examples directory, it's important that all files match the version of
 			Note: When using code from the examples directory, it's important that all files match the version of
-			your three.js main file. For example it's no good approach to use *GLTFLoader* and *OrbitControls* from R96 together
+			your three.js main file. For example, it's not acceptable to use *GLTFLoader* and *OrbitControls* from R96 together
 			with three.js R103. You can easily keep your files in sync by using the modules from the JSM directory. If the file
 			with three.js R103. You can easily keep your files in sync by using the modules from the JSM directory. If the file
 			is not available as a module, you can still use third-party npm packages or convert the file to a module by yourself.
 			is not available as a module, you can still use third-party npm packages or convert the file to a module by yourself.
 			In both cases, ensure the code is compatible with your three.js main file.
 			In both cases, ensure the code is compatible with your three.js main file.

+ 15 - 13
docs/manual/en/introduction/Useful-links.html

@@ -25,7 +25,7 @@
 
 
 		<h2>Help forums</h2>
 		<h2>Help forums</h2>
 		<p>
 		<p>
-			Three.js officially uses [link:http://stackoverflow.com/tags/three.js/info Stack Overflow] for help requests.
+			Three.js officially uses the [link:https://discourse.threejs.org/ forum] and [link:http://stackoverflow.com/tags/three.js/info Stack Overflow] for help requests.
 			If you need assistance with something, that's the place to go. Do NOT open an issue on Github for help requests.
 			If you need assistance with something, that's the place to go. Do NOT open an issue on Github for help requests.
 		</p>
 		</p>
 
 
@@ -46,6 +46,9 @@
 
 
 		<h3>More extensive / advanced articles and courses</h3>
 		<h3>More extensive / advanced articles and courses</h3>
 		<ul>
 		<ul>
+			<li>
+				[link:https://discoverthreejs.com/ Discover three.js]
+			</li>
 			<li>
 			<li>
 				[link:https://threejsfundamentals.org/ Three.js Fundamentals]
 				[link:https://threejsfundamentals.org/ Three.js Fundamentals]
 			</li>
 			</li>
@@ -66,21 +69,16 @@
 			 [link:http://learningthreejs.com/ Learning Three.js] – a blog with articles dedicated to teaching three.js
 			 [link:http://learningthreejs.com/ Learning Three.js] – a blog with articles dedicated to teaching three.js
 		 </li>
 		 </li>
 		 <li>
 		 <li>
-			 [link:http://bkcore.com/blog/3d/webgl-three-js-animated-selective-glow.html Animated selective glow in Three.js]
-			 by [link:https://github.com/BKcore BKcore]
+			 [link:https://discourse.threejs.org/t/three-js-bookshelf/2468 Three.js Bookshelf] - Looking for more resources about three.js or computer graphics in general?
+			 Check out the selection of literature recommended by the community.
 		 </li>
 		 </li>
 		</ul>
 		</ul>
 
 
-		<h3>Tutorials in other languages</h3>
+		<h2>News and Updates</h2>
 		<ul>
 		<ul>
 			<li>
 			<li>
-				[link:http://www.natural-science.or.jp/article/20120220155529.php Building A Physics Simulation Environment] - three.js tutorial in Japanese
+				[link:https://twitter.com/hashtag/threejs Three.js on Twitter]
 			</li>
 			</li>
-
-		</ul>
-
-		<h2>News and Updates</h2>
-		<ul>
 			<li>
 			<li>
 				[link:http://www.reddit.com/r/threejs/ Three.js on reddit]
 				[link:http://www.reddit.com/r/threejs/ Three.js on reddit]
 			</li>
 			</li>
@@ -90,9 +88,6 @@
 			<li>
 			<li>
 				[link:http://learningwebgl.com/blog/ Learning WebGL Blog] – The authoritive news source for WebGL.
 				[link:http://learningwebgl.com/blog/ Learning WebGL Blog] – The authoritive news source for WebGL.
 			</li>
 			</li>
-			<li>
-				[link:https://plus.google.com/104300307601542851567/posts Three.js posts] on Google+ – frequent posts on Three.js
-			</li>
 		</ul>
 		</ul>
 
 
 		<h2>Examples</h2>
 		<h2>Examples</h2>
@@ -179,6 +174,13 @@
 			[link:http://12devsofxmas.co.uk/2012/01/webgl-and-three-js/ A whirlwind look at Three.js]
 			[link:http://12devsofxmas.co.uk/2012/01/webgl-and-three-js/ A whirlwind look at Three.js]
 			by [link:http://github.com/nrocy Paul King]
 			by [link:http://github.com/nrocy Paul King]
 		</li>
 		</li>
+		<li>
+			[link:http://bkcore.com/blog/3d/webgl-three-js-animated-selective-glow.html Animated selective glow in Three.js]
+			by [link:https://github.com/BKcore BKcore]
+		</li>
+		<li>
+			[link:http://www.natural-science.or.jp/article/20120220155529.php Building A Physics Simulation Environment] - three.js tutorial in Japanese
+		</li>
 	 </ul>
 	 </ul>
 
 
 	</body>
 	</body>

+ 20 - 12
docs/manual/zh/introduction/Useful-links.html

@@ -31,6 +31,9 @@
 
 
 		<h3>three.js入门</h3>
 		<h3>three.js入门</h3>
 		<ul>
 		<ul>
+			<li>
+				[link:https://threejsfundamentals.org/threejs/lessons/threejs-fundamentals.html Three.js Fundamentals starting lesson]
+			</li>
 			<li>
 			<li>
 				[link:https://codepen.io/rachsmith/post/beginning-with-3d-webgl-pt-1-the-scene Beginning with 3D WebGL] by [link:https://codepen.io/rachsmith/ Rachel Smith].
 				[link:https://codepen.io/rachsmith/post/beginning-with-3d-webgl-pt-1-the-scene Beginning with 3D WebGL] by [link:https://codepen.io/rachsmith/ Rachel Smith].
 			</li>
 			</li>
@@ -41,6 +44,12 @@
 
 
 		<h3>更加广泛、高级的文章与教程</h3>
 		<h3>更加广泛、高级的文章与教程</h3>
 		<ul>
 		<ul>
+			<li>
+				[link:https://discoverthreejs.com/ Discover three.js]
+			</li>
+			<li>
+				[link:https://threejsfundamentals.org/ Three.js Fundamentals]
+			</li>
 			<li>
 			<li>
 				[link:http://blog.cjgammon.com/ Collection of tutorials] by [link:http://www.cjgammon.com/ CJ Gammon].
 				[link:http://blog.cjgammon.com/ Collection of tutorials] by [link:http://www.cjgammon.com/ CJ Gammon].
 			</li>
 			</li>
@@ -58,21 +67,16 @@
 			 [link:http://learningthreejs.com/ Learning Three.js] – a blog with articles dedicated to teaching three.js
 			 [link:http://learningthreejs.com/ Learning Three.js] – a blog with articles dedicated to teaching three.js
 		 </li>
 		 </li>
 		 <li>
 		 <li>
-			 [link:http://bkcore.com/blog/3d/webgl-three-js-animated-selective-glow.html Animated selective glow in Three.js]
-			 by [link:https://github.com/BKcore BKcore]
+			 [link:https://discourse.threejs.org/t/three-js-bookshelf/2468 Three.js Bookshelf] - Looking for more resources about three.js or computer graphics in general?
+			 Check out the selection of literature recommended by the community.
 		 </li>
 		 </li>
 		</ul>
 		</ul>
 
 
-		<h3>其它非英语的教程</h3>
+		<h2>新闻与更新</h2>
 		<ul>
 		<ul>
 			<li>
 			<li>
-				[link:http://www.natural-science.or.jp/article/20120220155529.php Building A Physics Simulation Environment] - three.js tutorial in Japanese
+				[link:https://twitter.com/hashtag/threejs Three.js on Twitter]
 			</li>
 			</li>
-
-		</ul>
-
-		<h2>新闻与更新</h2>
-		<ul>
 			<li>
 			<li>
 				[link:http://www.reddit.com/r/threejs/ Three.js on reddit]
 				[link:http://www.reddit.com/r/threejs/ Three.js on reddit]
 			</li>
 			</li>
@@ -82,9 +86,6 @@
 			<li>
 			<li>
 				[link:http://learningwebgl.com/blog/ Learning WebGL Blog] – The authoritive news source for WebGL.
 				[link:http://learningwebgl.com/blog/ Learning WebGL Blog] – The authoritive news source for WebGL.
 			</li>
 			</li>
-			<li>
-				[link:https://plus.google.com/104300307601542851567/posts Three.js posts] on Google+ – frequent posts on Three.js
-			</li>
 		</ul>
 		</ul>
 		<h2>示例</h2>
 		<h2>示例</h2>
 		<ul>
 		<ul>
@@ -165,6 +166,13 @@
 			[link:http://12devsofxmas.co.uk/2012/01/webgl-and-three-js/ A whirlwind look at Three.js]
 			[link:http://12devsofxmas.co.uk/2012/01/webgl-and-three-js/ A whirlwind look at Three.js]
 			by [link:http://github.com/nrocy Paul King]
 			by [link:http://github.com/nrocy Paul King]
 		</li>
 		</li>
+		<li>
+			[link:http://bkcore.com/blog/3d/webgl-three-js-animated-selective-glow.html Animated selective glow in Three.js]
+			by [link:https://github.com/BKcore BKcore]
+		</li>
+		<li>
+			[link:http://www.natural-science.or.jp/article/20120220155529.php Building A Physics Simulation Environment] - three.js tutorial in Japanese
+		</li>
 	 </ul>
 	 </ul>
 
 
 	</body>
 	</body>

+ 89 - 38
docs/page.css

@@ -1,6 +1,13 @@
+:root {
+	--color-blue: #049EF4;
+	--text-color: #444;
+	--border-style: 1px solid #EEE;
+	--header-height: 56px;
+}
+
 @font-face {
 @font-face {
-	font-family: 'RobotoMono';
-	src: local('RobotoMono'), url('../files/RobotoMono-Regular.woff2') format('woff2');
+	font-family: 'Roboto Mono';
+	src: local('Roboto Mono'), url('../files/RobotoMono-Regular.woff2') format('woff2');
 	font-weight: normal;
 	font-weight: normal;
 	font-style: normal;
 	font-style: normal;
 }
 }
@@ -13,54 +20,86 @@
 }
 }
 
 
 body {
 body {
-	margin: 78px auto;
-	padding: 0px 24px;
-	max-width: 780px;
-	color: #555;
+	padding: 20px 24px 40px 24px;
+	margin: 0;
+	color: var(--text-color);
 	font-family: 'SF-Pro-Text', sans-serif;
 	font-family: 'SF-Pro-Text', sans-serif;
 	font-size: 16px;
 	font-size: 16px;
-	line-height: 23px;
+	line-height: 24px;
 	tab-size: 4;
 	tab-size: 4;
 	overflow: auto;
 	overflow: auto;
 }
 }
 
 
 a {
 a {
-	color: #1184CE;
+	color: var(--color-blue);
 	cursor: pointer;
 	cursor: pointer;
-	text-decoration: underline;
+	text-decoration: none;
 }
 }
 
 
 h1 {
 h1 {
-	color: #049EF4;
-	font-size: 32px;
+	color: var(--color-blue);
+	font-size: 2.4em;
 	font-weight: normal;
 	font-weight: normal;
-	line-height: 42px;
+	line-height: 1.36em;
+	margin-top: 16px;
+	margin-bottom: -16px;
+	text-indent: -2px;
 }
 }
 
 
 h2 {
 h2 {
-	color: #4B0;
-
-	font-size: 22px;
+	color: var(--color-blue);
+	font-size: 1.8em;
+	line-height: 1.32em;
 	font-weight: normal;
 	font-weight: normal;
-	line-height: 31px;
+	margin-top: 40px;
+	margin-bottom: 12px;
+	text-indent: -1px;
 }
 }
 
 
 h3 {
 h3 {
-	color: #000;
-	font-size: 16px;
+	font-size: 1.32em;
+	line-height: 1.48em;
 	font-weight: normal;
 	font-weight: normal;
+	text-indent: -1px;
+	margin-top: 24px;
+	margin-bottom: 12px;
+}
 
 
-	margin-top: 40px;
+p {
+	margin-top: 24px;
+	margin-bottom: 24px;
+}
+ul, ol {
+	box-sizing: border-box;
+	padding-left: 20px;
+}
+ul li,
+ol li {
+	padding-left: 4px;
+	margin-bottom: 4px;
+}
+
+li ul,
+li ol {
+	margin-top: 4px;
 }
 }
 
 
-p, ul, ol {
-	margin-top: 0;
+body {
+	max-width: 760px;
+	margin-left: auto;
+	margin-right: auto;
+}
+
+table,
+pre,
+code {
+	margin-left: -24px;
+	margin-right: -24px;
+	margin-top: 20px;
 	margin-bottom: 20px;
 	margin-bottom: 20px;
-	max-width: 780px;
 }
 }
 
 
 div {
 div {
-	/* padding-left: 30px; */
 	margin-bottom: 20px;
 	margin-bottom: 20px;
 }
 }
 
 
@@ -68,17 +107,30 @@ div {
 	padding-left: 0px;
 	padding-left: 0px;
 }
 }
 
 
-pre, code {
-	margin-top: 20px;
-	margin-bottom: 20px;
+br {
+	display: none;
+}
+
+table {
+	border-spacing: 24px 4px;
+}
+table,
+table tr,
+table td {
+	text-align: left;
+}
+
+table th {
+	text-decoration: none;
+	padding: 2px 0;
 }
 }
 
 
 code {
 code {
 	display: block;
 	display: block;
-	padding: 20px;
+	padding: 20px 24px;
 	white-space: pre-wrap;
 	white-space: pre-wrap;
-	background-color: #f9f9f9;
 	overflow: auto;
 	overflow: auto;
+	box-sizing: border-box;
 }
 }
 
 
 iframe {
 iframe {
@@ -109,15 +161,15 @@ strong {
 
 
 #button {
 #button {
 	position: fixed;
 	position: fixed;
-	bottom: 16px;
-	right: 16px;
+	bottom: 12px;
+	right: 12px;
 
 
 	padding: 8px;
 	padding: 8px;
 	border-radius: 50%;
 	border-radius: 50%;
-	margin-bottom: 0px; /* TODO div sets it to 20px */
+	margin-bottom: 0px;
 
 
-	background-color: #dddddd;
-	opacity: 0.4;
+	background-color: #E5E5E5;
+	opacity: .9;
 }
 }
 
 
 	#button:hover {
 	#button:hover {
@@ -127,6 +179,7 @@ strong {
 
 
 	#button img {
 	#button img {
 		display: block;
 		display: block;
+		width: 20px;
 	}
 	}
 
 
 a.permalink {
 a.permalink {
@@ -157,19 +210,17 @@ sub {
 /* mobile */
 /* mobile */
 
 
 @media all and ( max-width: 640px ) {
 @media all and ( max-width: 640px ) {
-
 	body {
 	body {
-		margin: 14px auto;
-		padding: 0px 14px;
-		font-size: 14px;
-		line-height: 22px;
+		padding: 16px 20px;
 	}
 	}
 
 
 	h1 {
 	h1 {
+		margin-top: 0;
 		font-size: 26px;
 		font-size: 26px;
 	}
 	}
 
 
 	h2 {
 	h2 {
+		margin-top: 20px;
 		font-size: 18px;
 		font-size: 18px;
 		line-height: 25px;
 		line-height: 25px;
 	}
 	}

+ 2 - 2
docs/prettify/threejs.css

@@ -11,7 +11,7 @@ pre .dec, code .dec { color: #22c0c4; } /* decimal */
 
 
 pre.prettyprint, code.prettyprint {
 pre.prettyprint, code.prettyprint {
 	background-color: #F5F5F5;
 	background-color: #F5F5F5;
-	font-family: 'RobotoMono', monospace;
+	font-family: 'Roboto Mono', monospace;
 	font-size: 14px;
 	font-size: 14px;
-	line-height: 21px;
+	line-height: 24px;
 }
 }

+ 5 - 4
editor/manifest.json

@@ -1,13 +1,14 @@
 {
 {
-  "short_name": "Editor",
   "name": "Three.js Editor",
   "name": "Three.js Editor",
+  "short_name": "Three.js",
+  "start_url": ".",
+  "scope": ".",
+  "display": "standalone",
   "icons": [
   "icons": [
     {
     {
       "src": "./images/icon.png",
       "src": "./images/icon.png",
       "type": "image/png",
       "type": "image/png",
       "sizes": "144x144"
       "sizes": "144x144"
     }
     }
-  ],
-  "start_url": ".",
-  "display": "standalone"
+  ]
 }
 }

+ 2 - 2
examples/css3d_panorama_deviceorientation.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <!DOCTYPE html>
 <html>
 <html>
 	<head>
 	<head>
-		<title>three.js css3d - panorama - deviceorientation</title>
+		<title>three.js css3d - panorama - device orientation</title>
 		<meta charset="utf-8">
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<style>
 		<style>
@@ -34,7 +34,7 @@
 		<script src="js/controls/DeviceOrientationControls.js"></script>
 		<script src="js/controls/DeviceOrientationControls.js"></script>
 		<script src="js/renderers/CSS3DRenderer.js"></script>
 		<script src="js/renderers/CSS3DRenderer.js"></script>
 
 
-		<div id="info"><a href="http://threejs.org" target="_blank" rel="noopener">three.js css3d</a> - panorama - decideorientation. cubemap by <a href="http://www.humus.name/index.php?page=Textures" target="_blank" rel="noopener">Humus</a>.</div>
+		<div id="info"><a href="http://threejs.org" target="_blank" rel="noopener">three.js css3d</a> - panorama - device orientation. cubemap by <a href="http://www.humus.name/index.php?page=Textures" target="_blank" rel="noopener">Humus</a>.</div>
 
 
 		<script>
 		<script>
 
 

+ 1 - 0
examples/files.js

@@ -75,6 +75,7 @@ var files = {
 		"webgl_lines_sphere",
 		"webgl_lines_sphere",
 		"webgl_loader_3ds",
 		"webgl_loader_3ds",
 		"webgl_loader_3mf",
 		"webgl_loader_3mf",
+		"webgl_loader_3mf_materials",
 		"webgl_loader_amf",
 		"webgl_loader_amf",
 		"webgl_loader_assimp",
 		"webgl_loader_assimp",
 		"webgl_loader_assimp2json",
 		"webgl_loader_assimp2json",

+ 66 - 24
examples/index.html

@@ -9,24 +9,29 @@
 		<style>
 		<style>
 			#panel #content .link {
 			#panel #content .link {
 				display: block;
 				display: block;
-				text-decoration: none;
-				cursor: pointer;
 			}
 			}
-
-			#viewSrcButton {
+			#button {
 				position: fixed;
 				position: fixed;
-				bottom: 20px;
-				right: 20px;
+				bottom: 12px;
+				right: 12px;
+
 				padding: 8px;
 				padding: 8px;
-				color: #fff;
-				background-color: #555;
-				opacity: 0.7;
+				border-radius: 50%;
+				margin-bottom: 0px; /* TODO div sets it to 20px */
+
+				background-color: #E5E5E5;
+				opacity: .9;
 			}
 			}
 
 
-			#viewSrcButton:hover {
+			#button:hover {
 				cursor: pointer;
 				cursor: pointer;
 				opacity: 1;
 				opacity: 1;
 			}
 			}
+
+			#button img {
+				display: block;
+				width: 20px;
+			}
 		</style>
 		</style>
 	</head>
 	</head>
 	<body>
 	<body>
@@ -34,25 +39,36 @@
 		<div id="panel">
 		<div id="panel">
 
 
 			<div id="header">
 			<div id="header">
-
 				<h1><a href="http://threejs.org">three.js</a></h1>
 				<h1><a href="http://threejs.org">three.js</a></h1>
 
 
-				<img id="expandButton" src="../files/ic_menu_black_24dp.svg">
-
 				<div id="sections">
 				<div id="sections">
-					<a href="../docs/">docs</a> <span class="selected">examples</span>
+					<a href="../docs/">docs</a>
+					<span class="selected">examples</span>
 				</div>
 				</div>
 
 
-				<input type="text" id="filter" autocorrect="off" autocapitalize="off" spellcheck="false"/>
-
+				<img id="expandButton" src="../files/ic_menu_black_24dp.svg">
 			</div>
 			</div>
 
 
-			<div id="content"></div>
+			<div id="panelScrim"></div>
+
+			<div id="contentWrapper">
+				<input placeholder="Search" type="text" id="filter" autocorrect="off" autocapitalize="off" spellcheck="false" />
+				<div id="exitSearchButton"></div>
+
+				<select id="language">
+					<option value="en">en</option>
+					<option value="zh">zh</option>
+				</select>
+
+				<div id="content"></div>
+			</div>
 
 
 		</div>
 		</div>
 
 
 		<iframe id="viewer" name="viewer" allowfullscreen allowvr onmousewheel=""></iframe>
 		<iframe id="viewer" name="viewer" allowfullscreen allowvr onmousewheel=""></iframe>
 
 
+		<a id="button" target="_blank"><img src="../files/ic_code_black_24dp.svg"></a>
+
 		<script src="files.js"></script>
 		<script src="files.js"></script>
 
 
 		<script>
 		<script>
@@ -70,13 +86,22 @@
 		var viewer = document.getElementById( 'viewer' );
 		var viewer = document.getElementById( 'viewer' );
 
 
 		var filterInput = document.getElementById( 'filter' );
 		var filterInput = document.getElementById( 'filter' );
+		var exitSearchButton = document.getElementById( 'exitSearchButton' );
 
 
 		var expandButton = document.getElementById( 'expandButton' );
 		var expandButton = document.getElementById( 'expandButton' );
 		expandButton.addEventListener( 'click', function ( event ) {
 		expandButton.addEventListener( 'click', function ( event ) {
 			event.preventDefault();
 			event.preventDefault();
-			panel.classList.toggle( 'collapsed' );
+			panel.classList.toggle( 'open' );
 		} );
 		} );
 
 
+		var panelScrim = document.getElementById( 'panelScrim' );
+		panelScrim.onclick = function ( event ) {
+
+			event.preventDefault();
+			panel.classList.toggle( 'open' );
+
+		};
+
 		// iOS iframe auto-resize workaround
 		// iOS iframe auto-resize workaround
 
 
 		if ( /(iPad|iPhone|iPod)/g.test( navigator.userAgent ) ) {
 		if ( /(iPad|iPhone|iPod)/g.test( navigator.userAgent ) ) {
@@ -90,12 +115,8 @@
 		var container = document.createElement( 'div' );
 		var container = document.createElement( 'div' );
 		content.appendChild( container );
 		content.appendChild( container );
 
 
-		var viewSrcButton = document.createElement( 'a' );
-		viewSrcButton.id = 'viewSrcButton';
-		viewSrcButton.target = '_blank';
-		viewSrcButton.textContent = 'View source';
+		var viewSrcButton = document.getElementById( 'button' );
 		viewSrcButton.style.display = 'none';
 		viewSrcButton.style.display = 'none';
-		document.body.appendChild( viewSrcButton );
 
 
 		var links = {};
 		var links = {};
 		var selected = null;
 		var selected = null;
@@ -157,7 +178,7 @@
 			window.location.hash = file;
 			window.location.hash = file;
 			viewer.focus();
 			viewer.focus();
 
 
-			panel.classList.add( 'collapsed' );
+			panel.classList.remove( 'open' );
 
 
 			selected = file;
 			selected = file;
 
 
@@ -175,6 +196,27 @@
 		}
 		}
 
 
 		// filter
 		// filter
+		filterInput.onfocus = function ( event ) {
+
+			panel.classList.add('searchFocused');
+
+		}
+
+		filterInput.onblur = function ( event ) {
+
+			if(filterInput.value === '') {
+				panel.classList.remove('searchFocused');
+			}
+
+		}
+
+		exitSearchButton.onclick = function( event ) {
+
+			filterInput.value = '';
+			updateFilter();
+			panel.classList.remove('searchFocused');
+
+		}
 
 
 		filterInput.addEventListener( 'input', function( e ) {
 		filterInput.addEventListener( 'input', function( e ) {
 
 

+ 6 - 1
examples/js/exporters/GLTFExporter.js

@@ -1740,7 +1740,12 @@ THREE.GLTFExporter.prototype = {
 
 
 			} else {
 			} else {
 
 
-				object.updateMatrix();
+				if ( object.matrixAutoUpdate ) {
+
+					object.updateMatrix();
+
+				}
+
 				if ( ! equalArray( object.matrix.elements, [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] ) ) {
 				if ( ! equalArray( object.matrix.elements, [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] ) ) {
 
 
 					gltfNode.matrix = object.matrix.elements;
 					gltfNode.matrix = object.matrix.elements;

+ 343 - 44
examples/js/loaders/3MFLoader.js

@@ -72,7 +72,7 @@ THREE.ThreeMFLoader.prototype = {
 
 
 			for ( file in zip.files ) {
 			for ( file in zip.files ) {
 
 
-				if ( file.match( /\.rels$/ ) ) {
+				if ( file.match( /\_rels\/.rels$/ ) ) {
 
 
 					relsName = file;
 					relsName = file;
 
 
@@ -206,9 +206,38 @@ THREE.ThreeMFLoader.prototype = {
 		}
 		}
 
 
 		function parseBasematerialsNode( basematerialsNode ) {
 		function parseBasematerialsNode( basematerialsNode ) {
+
+			var basematerialsData = {
+				id: basematerialsNode.getAttribute( 'id' ), // required
+				basematerials: []
+			};
+
+			var basematerialNodes = basematerialsNode.querySelectorAll( 'base' );
+
+			for ( var i = 0; i < basematerialNodes.length; i ++ ) {
+
+				var basematerialNode = basematerialNodes[ i ];
+				var basematerialData = parseBasematerialNode( basematerialNode );
+				basematerialsData.basematerials.push( basematerialData );
+
+			}
+
+			return basematerialsData;
+
 		}
 		}
 
 
-		function parseMeshNode( meshNode, extensions ) {
+		function parseBasematerialNode( basematerialNode ) {
+
+			var basematerialData = {};
+
+			basematerialData[ 'name' ] = basematerialNode.getAttribute( 'name' ); // required
+			basematerialData[ 'displaycolor' ] = basematerialNode.getAttribute( 'displaycolor' ); // required
+
+			return basematerialData;
+
+		}
+
+		function parseMeshNode( meshNode ) {
 
 
 			var meshData = {};
 			var meshData = {};
 
 
@@ -300,6 +329,59 @@ THREE.ThreeMFLoader.prototype = {
 
 
 		function parseComponentsNode( componentsNode ) {
 		function parseComponentsNode( componentsNode ) {
 
 
+			var components = [];
+
+			var componentNodes = componentsNode.querySelectorAll( 'component' );
+
+			for ( var i = 0; i < componentNodes.length; i ++ ) {
+
+				var componentNode = componentNodes[ i ];
+				var componentData = parseComponentNode( componentNode );
+				components.push( componentData );
+
+			}
+
+			return components;
+
+		}
+
+		function parseComponentNode( componentNode ) {
+
+			var componentData = {};
+
+			componentData[ 'objectId' ] = componentNode.getAttribute( 'objectid' ); // required
+
+			var transform = componentNode.getAttribute( 'transform' );
+
+			if ( transform ) {
+
+				componentData[ 'transform' ] = parseTransform( transform );
+
+			}
+
+			return componentData;
+
+		}
+
+		function parseTransform( transform ) {
+
+			var t = [];
+			transform.split( ' ' ).forEach( function ( s ) {
+
+				t.push( parseFloat( s ) );
+
+			} );
+
+			var matrix = new THREE.Matrix4();
+			matrix.set(
+				t[ 0 ], t[ 3 ], t[ 6 ], t[ 9 ],
+				t[ 1 ], t[ 4 ], t[ 7 ], t[ 10 ],
+				t[ 2 ], t[ 5 ], t[ 8 ], t[ 11 ],
+				 0.0, 0.0, 0.0, 1.0
+			);
+
+			return matrix;
+
 		}
 		}
 
 
 		function parseObjectNode( objectNode ) {
 		function parseObjectNode( objectNode ) {
@@ -383,7 +465,7 @@ THREE.ThreeMFLoader.prototype = {
 
 
 			if ( basematerialsNode ) {
 			if ( basematerialsNode ) {
 
 
-				resourcesData[ 'basematerial' ] = parseBasematerialsNode( basematerialsNode );
+				resourcesData[ 'basematerials' ] = parseBasematerialsNode( basematerialsNode );
 
 
 			}
 			}
 
 
@@ -411,25 +493,13 @@ THREE.ThreeMFLoader.prototype = {
 
 
 				var itemNode = itemNodes[ i ];
 				var itemNode = itemNodes[ i ];
 				var buildItem = {
 				var buildItem = {
-					objectid: itemNode.getAttribute( 'objectid' )
+					objectId: itemNode.getAttribute( 'objectid' )
 				};
 				};
 				var transform = itemNode.getAttribute( 'transform' );
 				var transform = itemNode.getAttribute( 'transform' );
 
 
 				if ( transform ) {
 				if ( transform ) {
 
 
-					var t = [];
-					transform.split( ' ' ).forEach( function ( s ) {
-
-						t.push( parseFloat( s ) );
-
-					} );
-					var mat4 = new THREE.Matrix4();
-					buildItem[ 'transform' ] = mat4.set(
-						t[ 0 ], t[ 3 ], t[ 6 ], t[ 9 ],
-						t[ 1 ], t[ 4 ], t[ 7 ], t[ 10 ],
-						t[ 2 ], t[ 5 ], t[ 8 ], t[ 11 ],
-						 0.0, 0.0, 0.0, 1.0
-					);
+					buildItem[ 'transform' ] = parseTransform( transform );
 
 
 				}
 				}
 
 
@@ -472,40 +542,172 @@ THREE.ThreeMFLoader.prototype = {
 
 
 		}
 		}
 
 
-		function buildMesh( meshData, data3mf ) {
+		function buildMesh( meshData, objects, modelData, objectData ) {
+
+			// geometry
 
 
 			var geometry = new THREE.BufferGeometry();
 			var geometry = new THREE.BufferGeometry();
 			geometry.setIndex( new THREE.BufferAttribute( meshData[ 'triangles' ], 1 ) );
 			geometry.setIndex( new THREE.BufferAttribute( meshData[ 'triangles' ], 1 ) );
 			geometry.addAttribute( 'position', new THREE.BufferAttribute( meshData[ 'vertices' ], 3 ) );
 			geometry.addAttribute( 'position', new THREE.BufferAttribute( meshData[ 'vertices' ], 3 ) );
 
 
-			if ( meshData[ 'colors' ] ) {
+			// groups
+
+			var basematerialsData = modelData[ 'resources' ][ 'basematerials' ];
+			var triangleProperties = meshData[ 'triangleProperties' ];
 
 
-				geometry.addAttribute( 'color', new THREE.BufferAttribute( meshData[ 'colors' ], 3 ) );
+			var start = 0;
+			var count = 0;
+			var currentMaterialIndex = - 1;
+
+			for ( var i = 0, l = triangleProperties.length; i < l; i ++ ) {
+
+				var triangleProperty = triangleProperties[ i ];
+				var pid = triangleProperty.pid;
+
+				// only proceed if the triangle refers to a basematerials definition
+
+				if ( basematerialsData && ( basematerialsData.id === pid ) ) {
+
+					if ( currentMaterialIndex === - 1 ) currentMaterialIndex = triangleProperty.p1;
+
+					if ( currentMaterialIndex === triangleProperty.p1 ) {
+
+						count += 3; // primitves per triangle
+
+					} else {
+
+						geometry.addGroup( start, count, currentMaterialIndex );
+
+						start += count;
+						count = 3;
+						currentMaterialIndex = triangleProperty.p1;
+
+					}
+
+				}
 
 
 			}
 			}
 
 
+			if ( geometry.groups.length > 0 ) mergeGroups( geometry );
+
 			geometry.computeBoundingSphere();
 			geometry.computeBoundingSphere();
 
 
-			var materialOpts = {
-				flatShading: true
-			};
+			// material
+
+			var material;
+
+			if ( basematerialsData && ( basematerialsData.id === objectData.pid ) ) {
+
+				var materialIndex = objectData.pindex;
+				var basematerialData = basematerialsData.basematerials[ materialIndex ];
+
+				material = getBuild( basematerialData, objects, modelData, objectData, buildBasematerial );
+
+			} else if ( geometry.groups.length > 0 ) {
+
+				var groups = geometry.groups;
+				material = [];
 
 
-			if ( meshData[ 'colors' ] && 0 < meshData[ 'colors' ].length ) {
+				for ( var i = 0, l = groups.length; i < l; i ++ ) {
 
 
-				materialOpts[ 'vertexColors' ] = THREE.VertexColors;
+					var group = groups[ i ];
+					var basematerialData = basematerialsData.basematerials[ group.materialIndex ];
+
+					material.push( getBuild( basematerialData, objects, modelData, objectData, buildBasematerial ) );
+
+				}
 
 
 			} else {
 			} else {
 
 
-				materialOpts[ 'color' ] = 0xaaaaff;
+				// default material
+
+				material = new THREE.MeshPhongMaterial( { color: 0xaaaaff, flatShading: true } );
 
 
 			}
 			}
 
 
-			var material = new THREE.MeshPhongMaterial( materialOpts );
 			return new THREE.Mesh( geometry, material );
 			return new THREE.Mesh( geometry, material );
 
 
 		}
 		}
 
 
-		function applyExtensions( extensions, meshData, modelXml, data3mf ) {
+		function mergeGroups( geometry ) {
+
+			// sort by material index
+
+			var groups = geometry.groups.sort( function ( a, b ) {
+
+				if ( a.materialIndex !== b.materialIndex ) return a.materialIndex - b.materialIndex;
+
+				return a.start - b.start;
+
+			} );
+
+			// reorganize index buffer
+
+			var index = geometry.index;
+
+			var itemSize = index.itemSize;
+			var srcArray = index.array;
+
+			var targetOffset = 0;
+
+			var targetArray = new srcArray.constructor( srcArray.length );
+
+			for ( var i = 0; i < groups.length; i ++ ) {
+
+				var group = groups[ i ];
+
+				var groupLength = group.count * itemSize;
+				var groupStart = group.start * itemSize;
+
+				var sub = srcArray.subarray( groupStart, groupStart + groupLength );
+
+				targetArray.set( sub, targetOffset );
+
+				targetOffset += groupLength;
+
+			}
+
+			srcArray.set( targetArray );
+
+			// update groups
+
+			var start = 0;
+
+			for ( i = 0; i < groups.length; i ++ ) {
+
+				group = groups[ i ];
+
+				group.start = start;
+				start += group.count;
+
+			}
+
+			// merge groups
+
+			var lastGroup = groups[ 0 ];
+
+			geometry.groups = [ lastGroup ];
+
+			for ( i = 1; i < groups.length; i ++ ) {
+
+				group = groups[ i ];
+
+				if ( lastGroup.materialIndex === group.materialIndex ) {
+
+					lastGroup.count += group.count;
+
+				} else {
+
+					lastGroup = group;
+					geometry.groups.push( lastGroup );
+
+				}
+
+			}
+
+		}
+
+		function applyExtensions( extensions, meshData, modelXml ) {
 
 
 			if ( ! extensions ) {
 			if ( ! extensions ) {
 
 
@@ -543,38 +745,131 @@ THREE.ThreeMFLoader.prototype = {
 
 
 		}
 		}
 
 
-		function buildMeshes( data3mf ) {
+		function getBuild( data, objects, modelData, objectData, builder ) {
+
+			if ( data.build !== undefined ) return data.build;
+
+			data.build = builder( data, objects, modelData, objectData );
+
+			return data.build;
+
+		}
+
+		function buildBasematerial( materialData ) {
+
+			var material = new THREE.MeshPhongMaterial( { flatShading: true } );
+
+			material.name = materialData.name;
+
+			// displaycolor MUST be specified with a value of a 6 or 8 digit hexadecimal number, e.g. "#RRGGBB" or "#RRGGBBAA"
+
+			var displaycolor = materialData.displaycolor;
+
+			var color = displaycolor.substring( 0, 7 );
+			material.color.setStyle( color );
+			material.color.convertSRGBToLinear(); // displaycolor is in sRGB
+
+			// process alpha if set
+
+			if ( displaycolor.length === 9 ) {
+
+				material.opacity = parseInt( displaycolor.charAt( 7 ) + displaycolor.charAt( 8 ), 16 ) / 255;
+
+			}
+
+			return material;
+
+		}
+
+		function buildComposite( compositeData, objects, modelData ) {
+
+			var composite = new THREE.Group();
+
+			for ( var j = 0; j < compositeData.length; j ++ ) {
+
+				var component = compositeData[ j ];
+				var build = objects[ component.objectId ];
+
+				if ( build === undefined ) {
+
+					buildObject( component.objectId, objects, modelData );
+					build = objects[ component.objectId ];
+
+				}
+
+				var object3D = build.clone();
+
+				// apply component transfrom
+
+				var transform = component.transform;
+
+				if ( transform ) {
+
+					object3D.applyMatrix( transform );
+
+				}
+
+				composite.add( object3D );
+
+			}
+
+			return composite;
+
+		}
+
+		function buildObject( objectId, objects, modelData ) {
+
+			var objectData = modelData[ 'resources' ][ 'object' ][ objectId ];
+
+			if ( objectData[ 'mesh' ] ) {
+
+				var meshData = objectData[ 'mesh' ];
+
+				var extensions = modelData[ 'extensions' ];
+				var modelXml = modelData[ 'xml' ];
+
+				applyExtensions( extensions, meshData, modelXml );
+
+				objects[ objectData.id ] = getBuild( meshData, objects, modelData, objectData, buildMesh );
+
+			} else {
+
+				var compositeData = objectData[ 'components' ];
+
+				objects[ objectData.id ] = getBuild( compositeData, objects, modelData, objectData, buildComposite );
+
+			}
+
+		}
+
+		function buildObjects( data3mf ) {
 
 
 			var modelsData = data3mf.model;
 			var modelsData = data3mf.model;
-			var meshes = {};
+			var objects = {};
 			var modelsKeys = Object.keys( modelsData );
 			var modelsKeys = Object.keys( modelsData );
 
 
 			for ( var i = 0; i < modelsKeys.length; i ++ ) {
 			for ( var i = 0; i < modelsKeys.length; i ++ ) {
 
 
 				var modelsKey = modelsKeys[ i ];
 				var modelsKey = modelsKeys[ i ];
 				var modelData = modelsData[ modelsKey ];
 				var modelData = modelsData[ modelsKey ];
-				var modelXml = modelData[ 'xml' ];
-				var extensions = modelData[ 'extensions' ];
 
 
 				var objectIds = Object.keys( modelData[ 'resources' ][ 'object' ] );
 				var objectIds = Object.keys( modelData[ 'resources' ][ 'object' ] );
 
 
 				for ( var j = 0; j < objectIds.length; j ++ ) {
 				for ( var j = 0; j < objectIds.length; j ++ ) {
 
 
 					var objectId = objectIds[ j ];
 					var objectId = objectIds[ j ];
-					var objectData = modelData[ 'resources' ][ 'object' ][ objectId ];
-					var meshData = objectData[ 'mesh' ];
-					applyExtensions( extensions, meshData, modelXml, data3mf );
-					meshes[ objectId ] = buildMesh( meshData, data3mf );
+
+					buildObject( objectId, objects, modelData );
 
 
 				}
 				}
 
 
 			}
 			}
 
 
-			return meshes;
+			return objects;
 
 
 		}
 		}
 
 
-		function build( meshes, refs, data3mf ) {
+		function build( objects, refs, data3mf ) {
 
 
 			var group = new THREE.Group();
 			var group = new THREE.Group();
 			var buildData = data3mf.model[ refs[ 'target' ].substring( 1 ) ][ 'build' ];
 			var buildData = data3mf.model[ refs[ 'target' ].substring( 1 ) ][ 'build' ];
@@ -582,15 +877,19 @@ THREE.ThreeMFLoader.prototype = {
 			for ( var i = 0; i < buildData.length; i ++ ) {
 			for ( var i = 0; i < buildData.length; i ++ ) {
 
 
 				var buildItem = buildData[ i ];
 				var buildItem = buildData[ i ];
-				var mesh = meshes[ buildItem[ 'objectid' ] ];
+				var object3D = objects[ buildItem[ 'objectId' ] ];
+
+				// apply transform
 
 
-				if ( buildItem[ 'transform' ] ) {
+				var transform = buildItem[ 'transform' ];
+
+				if ( transform ) {
 
 
-					mesh.geometry.applyMatrix( buildItem[ 'transform' ] );
+					object3D.applyMatrix( transform );
 
 
 				}
 				}
 
 
-				group.add( mesh );
+				group.add( object3D );
 
 
 			}
 			}
 
 
@@ -599,9 +898,9 @@ THREE.ThreeMFLoader.prototype = {
 		}
 		}
 
 
 		var data3mf = loadDocument( data );
 		var data3mf = loadDocument( data );
-		var meshes = buildMeshes( data3mf );
+		var objects = buildObjects( data3mf );
 
 
-		return build( meshes, data3mf[ 'rels' ], data3mf );
+		return build( objects, data3mf[ 'rels' ], data3mf );
 
 
 	},
 	},
 
 

+ 4 - 2
examples/js/loaders/GLTFLoader.js

@@ -841,7 +841,8 @@ THREE.GLTFLoader = ( function () {
 
 
 				for ( var i = 0, il = params.length; i < il; i ++ ) {
 				for ( var i = 0, il = params.length; i < il; i ++ ) {
 
 
-					target[ params[ i ] ] = source[ params[ i ] ];
+					var value = source[ params[ i ] ];
+					target[ params[ i ] ] = value.isColor ? value.clone() : value;
 
 
 				}
 				}
 
 
@@ -1299,7 +1300,7 @@ THREE.GLTFLoader = ( function () {
 
 
 			if ( typeof gltfDef.extras === 'object' ) {
 			if ( typeof gltfDef.extras === 'object' ) {
 
 
-				object.userData = gltfDef.extras;
+				Object.assign( object.userData, gltfDef.extras );
 
 
 			} else {
 			} else {
 
 
@@ -2996,6 +2997,7 @@ THREE.GLTFLoader = ( function () {
 
 
 			if ( nodeDef.name !== undefined ) {
 			if ( nodeDef.name !== undefined ) {
 
 
+				node.userData.name = nodeDef.name;
 				node.name = THREE.PropertyBinding.sanitizeNodeName( nodeDef.name );
 				node.name = THREE.PropertyBinding.sanitizeNodeName( nodeDef.name );
 
 
 			}
 			}

+ 34 - 7
examples/js/postprocessing/EffectComposer.js

@@ -15,10 +15,20 @@ THREE.EffectComposer = function ( renderer, renderTarget ) {
 			stencilBuffer: false
 			stencilBuffer: false
 		};
 		};
 
 
-		var size = renderer.getDrawingBufferSize( new THREE.Vector2() );
-		renderTarget = new THREE.WebGLRenderTarget( size.width, size.height, parameters );
+		var size = renderer.getSize( new THREE.Vector2() );
+		this._pixelRatio = renderer.getPixelRatio();
+		this._width = size.width;
+		this._height = size.height;
+
+		renderTarget = new THREE.WebGLRenderTarget( this._width * this._pixelRatio, this._height * this._pixelRatio, parameters );
 		renderTarget.texture.name = 'EffectComposer.rt1';
 		renderTarget.texture.name = 'EffectComposer.rt1';
 
 
+	} else {
+
+		this._pixelRatio = 1;
+		this._width = renderTarget.width;
+		this._height = renderTarget.height;
+
 	}
 	}
 
 
 	this.renderTarget1 = renderTarget;
 	this.renderTarget1 = renderTarget;
@@ -162,10 +172,13 @@ Object.assign( THREE.EffectComposer.prototype, {
 
 
 		if ( renderTarget === undefined ) {
 		if ( renderTarget === undefined ) {
 
 
-			var size = this.renderer.getDrawingBufferSize( new THREE.Vector2() );
+			var size = this.renderer.getSize( new THREE.Vector2() );
+			this._pixelRatio = this.renderer.getPixelRatio();
+			this._width = size.width;
+			this._height = size.height;
 
 
 			renderTarget = this.renderTarget1.clone();
 			renderTarget = this.renderTarget1.clone();
-			renderTarget.setSize( size.width, size.height );
+			renderTarget.setSize( this._width * this._pixelRatio, this._height * this._pixelRatio );
 
 
 		}
 		}
 
 
@@ -181,15 +194,29 @@ Object.assign( THREE.EffectComposer.prototype, {
 
 
 	setSize: function ( width, height ) {
 	setSize: function ( width, height ) {
 
 
-		this.renderTarget1.setSize( width, height );
-		this.renderTarget2.setSize( width, height );
+		this._width = width;
+		this._height = height;
+
+		var effectiveWidth = this._width * this._pixelRatio;
+		var effectiveHeight = this._height * this._pixelRatio;
+
+		this.renderTarget1.setSize( effectiveWidth, effectiveHeight );
+		this.renderTarget2.setSize( effectiveWidth, effectiveHeight );
 
 
 		for ( var i = 0; i < this.passes.length; i ++ ) {
 		for ( var i = 0; i < this.passes.length; i ++ ) {
 
 
-			this.passes[ i ].setSize( width, height );
+			this.passes[ i ].setSize( effectiveWidth, effectiveHeight );
 
 
 		}
 		}
 
 
+	},
+
+	setPixelRatio: function ( pixelRatio ) {
+
+		this._pixelRatio = pixelRatio;
+
+		this.setSize( this._width, this._height );
+
 	}
 	}
 
 
 } );
 } );

+ 2 - 3
examples/misc_controls_fly.html

@@ -252,12 +252,11 @@
 				SCREEN_HEIGHT = window.innerHeight;
 				SCREEN_HEIGHT = window.innerHeight;
 				SCREEN_WIDTH = window.innerWidth;
 				SCREEN_WIDTH = window.innerWidth;
 
 
-				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
-
 				camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
 				camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
 				camera.updateProjectionMatrix();
 				camera.updateProjectionMatrix();
 
 
-				composer.reset();
+				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
+				composer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 
 
 			}
 			}
 
 

BIN
examples/models/3mf/truck.3mf


BIN
examples/models/kmz/Box.kmz


BIN
examples/textures/memorial.exr


BIN
examples/textures/memorial.hdr


File diff suppressed because it is too large
+ 0 - 10
examples/textures/miranda_uncropped.hdr


+ 5 - 5
examples/webgl_buffergeometry_lines.html

@@ -50,7 +50,7 @@
 
 
 			var camera, scene, renderer;
 			var camera, scene, renderer;
 
 
-			var mesh;
+			var line;
 
 
 			init();
 			init();
 			animate();
 			animate();
@@ -99,8 +99,8 @@
 
 
 				geometry.computeBoundingSphere();
 				geometry.computeBoundingSphere();
 
 
-				mesh = new THREE.Line( geometry, material );
-				scene.add( mesh );
+				line = new THREE.Line( geometry, material );
+				scene.add( line );
 
 
 				//
 				//
 
 
@@ -148,8 +148,8 @@
 
 
 				var time = Date.now() * 0.001;
 				var time = Date.now() * 0.001;
 
 
-				mesh.rotation.x = time * 0.25;
-				mesh.rotation.y = time * 0.5;
+				line.rotation.x = time * 0.25;
+				line.rotation.y = time * 0.5;
 
 
 				renderer.render( scene, camera );
 				renderer.render( scene, camera );
 
 

+ 5 - 5
examples/webgl_buffergeometry_lines_indexed.html

@@ -50,7 +50,7 @@
 
 
 			var camera, scene, renderer;
 			var camera, scene, renderer;
 
 
-			var mesh, parent_node;
+			var parent_node;
 
 
 			init();
 			init();
 			animate();
 			animate();
@@ -201,12 +201,12 @@
 				geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
 				geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
 				geometry.computeBoundingSphere();
 				geometry.computeBoundingSphere();
 
 
-				mesh = new THREE.LineSegments( geometry, material );
-				mesh.position.x -= 1200;
-				mesh.position.y -= 1200;
+				var lineSegments = new THREE.LineSegments( geometry, material );
+				lineSegments.position.x -= 1200;
+				lineSegments.position.y -= 1200;
 
 
 				parent_node = new THREE.Object3D();
 				parent_node = new THREE.Object3D();
-				parent_node.add( mesh );
+				parent_node.add( lineSegments );
 
 
 				scene.add( parent_node );
 				scene.add( parent_node );
 
 

+ 6 - 6
examples/webgl_custom_attributes_lines.html

@@ -83,7 +83,7 @@
 
 
 		var renderer, scene, camera, stats;
 		var renderer, scene, camera, stats;
 
 
-		var object, uniforms;
+		var line, uniforms;
 
 
 		var loader = new THREE.FontLoader();
 		var loader = new THREE.FontLoader();
 		loader.load( 'fonts/helvetiker_bold.typeface.json', function ( font ) {
 		loader.load( 'fonts/helvetiker_bold.typeface.json', function ( font ) {
@@ -155,9 +155,9 @@
 
 
 			}
 			}
 
 
-			object = new THREE.Line( geometry, shaderMaterial );
-			object.rotation.x = 0.2;
-			scene.add( object );
+			line = new THREE.Line( geometry, shaderMaterial );
+			line.rotation.x = 0.2;
+			scene.add( line );
 
 
 			renderer = new THREE.WebGLRenderer( { antialias: true } );
 			renderer = new THREE.WebGLRenderer( { antialias: true } );
 			renderer.setPixelRatio( window.devicePixelRatio );
 			renderer.setPixelRatio( window.devicePixelRatio );
@@ -197,12 +197,12 @@
 
 
 			var time = Date.now() * 0.001;
 			var time = Date.now() * 0.001;
 
 
-			object.rotation.y = 0.25 * time;
+			line.rotation.y = 0.25 * time;
 
 
 			uniforms.amplitude.value = Math.sin( 0.5 * time );
 			uniforms.amplitude.value = Math.sin( 0.5 * time );
 			uniforms.color.value.offsetHSL( 0.0005, 0, 0 );
 			uniforms.color.value.offsetHSL( 0.0005, 0, 0 );
 
 
-			var attributes = object.geometry.attributes;
+			var attributes = line.geometry.attributes;
 			var array = attributes.displacement.array;
 			var array = attributes.displacement.array;
 
 
 			for ( var i = 0, l = array.length; i < l; i += 3 ) {
 			for ( var i = 0, l = array.length; i < l; i += 3 ) {

+ 158 - 0
examples/webgl_loader_3mf_materials.html

@@ -0,0 +1,158 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - 3MF</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 {
+				color: #fff;
+				font-family:Monospace;
+				font-size:13px;
+				text-align:center;
+				background-color: #fff;
+				margin: 0px;
+				overflow: hidden;
+			}
+			#info {
+				position: absolute;
+				top: 0px; width: 100%;
+				padding: 5px;
+			}
+			a {
+				color: #ff0000;
+			}
+		</style>
+	</head>
+	<body>
+		<div id="info">
+			<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a>
+			<a href="http://3mf.io" target="_blank" rel="noopener">3MF file with materials</a>
+		</div>
+
+		<script src="../build/three.js"></script>
+		<script src="js/loaders/3MFLoader.js"></script>
+
+		<script src="js/WebGL.js"></script>
+		<script src="js/controls/OrbitControls.js"></script>
+
+		<script src="js/libs/jszip.min.js"></script>
+
+		<script>
+
+			if ( WEBGL.isWebGLAvailable() === false ) {
+
+				document.body.appendChild( WEBGL.getWebGLErrorMessage() );
+
+			}
+
+			var camera, scene, renderer;
+
+			init();
+
+			function init() {
+
+				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xa0a0a0 );
+				scene.fog = new THREE.Fog( 0xa0a0a0, 10, 500 );
+
+				scene.add( new THREE.AmbientLight( 0xffffff, 0.2 ) );
+
+				camera = new THREE.PerspectiveCamera( 35, window.innerWidth / window.innerHeight, 1, 500 );
+				camera.position.set( - 50, 40, 50 );
+				scene.add( camera );
+
+				//
+
+				var hemiLight = new THREE.HemisphereLight( 0xffffff, 0x444444 );
+				hemiLight.position.set( 0, 100, 0 );
+				scene.add( hemiLight );
+
+				var dirLight = new THREE.DirectionalLight( 0xffffff );
+				dirLight.position.set( - 0, 40, 50 );
+				dirLight.castShadow = true;
+				dirLight.shadow.camera.top = 50;
+				dirLight.shadow.camera.bottom = - 25;
+				dirLight.shadow.camera.left = - 25;
+				dirLight.shadow.camera.right = 25;
+				dirLight.shadow.camera.near = 0.1;
+				dirLight.shadow.camera.far = 200;
+				dirLight.shadow.mapSize.set( 1024, 1024 );
+				scene.add( dirLight );
+
+				// scene.add( new THREE.CameraHelper( dirLight.shadow.camera ) );
+
+				//
+
+				var loader = new THREE.ThreeMFLoader();
+				loader.load( './models/3mf/truck.3mf', function ( object ) {
+
+					object.quaternion.setFromEuler( new THREE.Euler( - Math.PI / 2, 0, 0 ) ); 	// z-up conversion
+
+					object.traverse( function ( child ) {
+
+						child.castShadow = true;
+
+					} );
+
+					scene.add( object );
+
+					render();
+
+				} );
+
+				//
+
+				var ground = new THREE.Mesh( new THREE.PlaneBufferGeometry( 1000, 1000 ), new THREE.MeshPhongMaterial( { color: 0x999999, depthWrite: false } ) );
+				ground.rotation.x = - Math.PI / 2;
+				ground.position.y = 11;
+				ground.receiveShadow = true;
+				scene.add( ground );
+
+				//
+
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.gammaOutput = true;
+				renderer.gammaFactor = 2.2;
+				renderer.shadowMap.enabled = true;
+				renderer.shadowMap.type = THREE.PCFSoftShadowMap;
+				document.body.appendChild( renderer.domElement );
+
+				//
+
+				var controls = new THREE.OrbitControls( camera, renderer.domElement );
+				controls.addEventListener( 'change', render );
+				controls.minDistance = 50;
+				controls.maxDistance = 200;
+				controls.enablePan = false;
+				controls.target.set( 0, 20, 0 );
+				controls.update();
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+				render();
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+				render();
+
+			}
+
+			function render() {
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+	</body>
+</html>

+ 6 - 5
examples/webgl_loader_texture_exr.html

@@ -32,7 +32,8 @@
 	<body>
 	<body>
 
 
 		<div id="info">
 		<div id="info">
-			<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl EXR texture loader example
+			<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl EXR texture loader example<br/>
+			Image courtesy of <a href="http://www.pauldebevec.com/Research/HDR/" target="_blank" rel="noopener">Paul Debevec</a>.
 		</div>
 		</div>
 
 
 		<script src="../build/three.js"></script>
 		<script src="../build/three.js"></script>
@@ -51,7 +52,7 @@
 			}
 			}
 
 
 			var params = {
 			var params = {
-				exposure: 1.0
+				exposure: 2.0
 			};
 			};
 
 
 			var renderer, scene, camera;
 			var renderer, scene, camera;
@@ -76,7 +77,7 @@
 
 
 				camera = new THREE.OrthographicCamera( - aspect, aspect, 1, - 1, 0, 1 );
 				camera = new THREE.OrthographicCamera( - aspect, aspect, 1, - 1, 0, 1 );
 
 
-				new THREE.EXRLoader().load( 'textures/piz_compressed.exr', function ( texture, textureData ) {
+				new THREE.EXRLoader().load( 'textures/memorial.exr', function ( texture, textureData ) {
 
 
 					//console.log( textureData );
 					//console.log( textureData );
 					//console.log( texture );
 					//console.log( texture );
@@ -92,7 +93,7 @@
 
 
 					var material = new THREE.MeshBasicMaterial( { map: texture } );
 					var material = new THREE.MeshBasicMaterial( { map: texture } );
 
 
-					var quad = new THREE.PlaneBufferGeometry( textureData.width / textureData.height, 1 );
+					var quad = new THREE.PlaneBufferGeometry( 1.5 * textureData.width / textureData.height, 1.5 );
 
 
 					var mesh = new THREE.Mesh( quad, material );
 					var mesh = new THREE.Mesh( quad, material );
 
 
@@ -106,7 +107,7 @@
 
 
 				var gui = new dat.GUI();
 				var gui = new dat.GUI();
 
 
-				gui.add( params, 'exposure', 0, 2 ).onChange( render );
+				gui.add( params, 'exposure', 0, 4, 0.01 ).onChange( render );
 				gui.open();
 				gui.open();
 
 
 				//
 				//

+ 6 - 5
examples/webgl_loader_texture_hdr.html

@@ -32,7 +32,8 @@
 	<body>
 	<body>
 
 
 		<div id="info">
 		<div id="info">
-			<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl HDR (RGBE) texture loader example
+			<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl HDR (RGBE) texture loader example<br/>
+			Image courtesy of <a href="http://www.pauldebevec.com/Research/HDR/" target="_blank" rel="noopener">Paul Debevec</a>.
 		</div>
 		</div>
 
 
 		<script src="../build/three.js"></script>
 		<script src="../build/three.js"></script>
@@ -51,7 +52,7 @@
 			}
 			}
 
 
 			var params = {
 			var params = {
-				exposure: 1.0
+				exposure: 2.0
 			};
 			};
 
 
 			var renderer, scene, camera;
 			var renderer, scene, camera;
@@ -76,7 +77,7 @@
 
 
 				camera = new THREE.OrthographicCamera( - aspect, aspect, 1, - 1, 0, 1 );
 				camera = new THREE.OrthographicCamera( - aspect, aspect, 1, - 1, 0, 1 );
 
 
-				new THREE.RGBELoader().load( 'textures/miranda_uncropped.hdr', function ( texture, textureData ) {
+				new THREE.RGBELoader().load( 'textures/memorial.hdr', function ( texture, textureData ) {
 
 
 					//console.log( textureData );
 					//console.log( textureData );
 					//console.log( texture );
 					//console.log( texture );
@@ -88,7 +89,7 @@
 
 
 					var material = new THREE.MeshBasicMaterial( { map: texture } );
 					var material = new THREE.MeshBasicMaterial( { map: texture } );
 
 
-					var quad = new THREE.PlaneBufferGeometry( textureData.width / textureData.height, 1 );
+					var quad = new THREE.PlaneBufferGeometry( 1.5 * textureData.width / textureData.height, 1.5 );
 
 
 					var mesh = new THREE.Mesh( quad, material );
 					var mesh = new THREE.Mesh( quad, material );
 
 
@@ -102,7 +103,7 @@
 
 
 				var gui = new dat.GUI();
 				var gui = new dat.GUI();
 
 
-				gui.add( params, 'exposure', 0, 2 ).onChange( render );
+				gui.add( params, 'exposure', 0, 4, 0.01 ).onChange( render );
 				gui.open();
 				gui.open();
 
 
 				//
 				//

+ 1 - 1
examples/webgl_materials_video.html

@@ -244,7 +244,7 @@
 				camera.updateProjectionMatrix();
 				camera.updateProjectionMatrix();
 
 
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
-				composer.reset();
+				composer.setSize( window.innerWidth, window.innerHeight );
 
 
 			}
 			}
 
 

+ 6 - 7
examples/webgl_points_dynamic.html

@@ -135,8 +135,8 @@
 
 
 				effectFocus = new THREE.ShaderPass( THREE.FocusShader );
 				effectFocus = new THREE.ShaderPass( THREE.FocusShader );
 
 
-				effectFocus.uniforms[ "screenWidth" ].value = window.innerWidth;
-				effectFocus.uniforms[ "screenHeight" ].value = window.innerHeight;
+				effectFocus.uniforms[ "screenWidth" ].value = window.innerWidth * window.devicePixelRatio;
+				effectFocus.uniforms[ "screenHeight" ].value = window.innerHeight * window.devicePixelRatio;
 
 
 				composer = new THREE.EffectComposer( renderer );
 				composer = new THREE.EffectComposer( renderer );
 
 
@@ -156,17 +156,16 @@
 
 
 			function onWindowResize() {
 			function onWindowResize() {
 
 
-				renderer.setSize( window.innerWidth, window.innerHeight );
-
 				camera.aspect = window.innerWidth / window.innerHeight;
 				camera.aspect = window.innerWidth / window.innerHeight;
 				camera.updateProjectionMatrix();
 				camera.updateProjectionMatrix();
 
 
 				camera.lookAt( scene.position );
 				camera.lookAt( scene.position );
 
 
-				composer.reset();
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				composer.setSize( window.innerWidth, window.innerHeight );
 
 
-				effectFocus.uniforms[ "screenWidth" ].value = window.innerWidth;
-				effectFocus.uniforms[ "screenHeight" ].value = window.innerHeight;
+				effectFocus.uniforms[ "screenWidth" ].value = window.innerWidth * window.devicePixelRatio;
+				effectFocus.uniforms[ "screenHeight" ].value = window.innerHeight * window.devicePixelRatio;
 
 
 			}
 			}
 
 

+ 1 - 5
examples/webgl_postprocessing_backgrounds.html

@@ -239,11 +239,7 @@
 				cameraO.updateProjectionMatrix();*/
 				cameraO.updateProjectionMatrix();*/
 
 
 				renderer.setSize( width, height );
 				renderer.setSize( width, height );
-
-				var pixelRatio = renderer.getPixelRatio();
-				var newWidth = Math.floor( width / pixelRatio ) || 1;
-				var newHeight = Math.floor( height / pixelRatio ) || 1;
-				composer.setSize( newWidth, newHeight );
+				composer.setSize( width, height );
 
 
 			}
 			}
 
 

+ 17 - 2
examples/webgl_postprocessing_masking.html

@@ -37,7 +37,7 @@
 
 
 			}
 			}
 
 
-			var composer, renderer;
+			var camera, composer, renderer;
 			var box, torus;
 			var box, torus;
 
 
 			init();
 			init();
@@ -45,7 +45,7 @@
 
 
 			function init() {
 			function init() {
 
 
-				var camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
+				camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
 				camera.position.z = 10;
 				camera.position.z = 10;
 
 
 				var scene1 = new THREE.Scene();
 				var scene1 = new THREE.Scene();
@@ -101,6 +101,21 @@
 				composer.addPass( clearMaskPass );
 				composer.addPass( clearMaskPass );
 				composer.addPass( outputPass );
 				composer.addPass( outputPass );
 
 
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				var width = window.innerWidth;
+				var height = window.innerHeight;
+
+				camera.aspect = width / height;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( width, height );
+				composer.setSize( width, height );
+
 			}
 			}
 
 
 			function animate() {
 			function animate() {

+ 1 - 5
examples/webgl_postprocessing_smaa.html

@@ -92,11 +92,7 @@
 				camera.updateProjectionMatrix();
 				camera.updateProjectionMatrix();
 
 
 				renderer.setSize( width, height );
 				renderer.setSize( width, height );
-
-				var pixelRatio = renderer.getPixelRatio();
-				var newWidth = Math.floor( width * pixelRatio ) || 1;
-				var newHeight = Math.floor( height * pixelRatio ) || 1;
-				composer.setSize( newWidth, newHeight );
+				composer.setSize( width, height );
 
 
 			}
 			}
 
 

+ 4 - 4
examples/webgl_postprocessing_sobel.html

@@ -118,8 +118,8 @@
 				// Sobel operator
 				// Sobel operator
 
 
 				effectSobel = new THREE.ShaderPass( THREE.SobelOperatorShader );
 				effectSobel = new THREE.ShaderPass( THREE.SobelOperatorShader );
-				effectSobel.uniforms[ "resolution" ].value.x = window.innerWidth;
-				effectSobel.uniforms[ "resolution" ].value.y = window.innerHeight;
+				effectSobel.uniforms[ 'resolution' ].value.x = window.innerWidth * window.devicePixelRatio;
+				effectSobel.uniforms[ 'resolution' ].value.y = window.innerHeight * window.devicePixelRatio;
 				composer.addPass( effectSobel );
 				composer.addPass( effectSobel );
 
 
 				var controls = new THREE.OrbitControls( camera, renderer.domElement );
 				var controls = new THREE.OrbitControls( camera, renderer.domElement );
@@ -145,8 +145,8 @@
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				composer.setSize( window.innerWidth, window.innerHeight );
 				composer.setSize( window.innerWidth, window.innerHeight );
 
 
-				effectSobel.uniforms[ "resolution" ].value.x = window.innerWidth;
-				effectSobel.uniforms[ "resolution" ].value.y = window.innerHeight;
+				effectSobel.uniforms[ 'resolution' ].value.x = window.innerWidth * window.devicePixelRatio;
+				effectSobel.uniforms[ 'resolution' ].value.y = window.innerHeight * window.devicePixelRatio;
 
 
 			}
 			}
 
 

+ 1 - 5
examples/webgl_postprocessing_ssaa.html

@@ -143,11 +143,7 @@
 				camera.updateProjectionMatrix();
 				camera.updateProjectionMatrix();
 
 
 				renderer.setSize( width, height );
 				renderer.setSize( width, height );
-
-				var pixelRatio = renderer.getPixelRatio();
-				var newWidth = Math.floor( width / pixelRatio ) || 1;
-				var newHeight = Math.floor( height / pixelRatio ) || 1;
-				composer.setSize( newWidth, newHeight );
+				composer.setSize( width, height );
 
 
 			}
 			}
 
 

+ 2 - 5
examples/webgl_postprocessing_ssaa_unbiased.html

@@ -177,6 +177,7 @@
 				// postprocessing
 				// postprocessing
 
 
 				composer = new THREE.EffectComposer( renderer );
 				composer = new THREE.EffectComposer( renderer );
+				composer.setPixelRatio( 1 ); // ensure pixel ratio is always 1 for performance reasons
 				ssaaRenderPassP = new THREE.SSAARenderPass( scene, cameraP );
 				ssaaRenderPassP = new THREE.SSAARenderPass( scene, cameraP );
 				composer.addPass( ssaaRenderPassP );
 				composer.addPass( ssaaRenderPassP );
 				ssaaRenderPassO = new THREE.SSAARenderPass( scene, cameraO );
 				ssaaRenderPassO = new THREE.SSAARenderPass( scene, cameraO );
@@ -204,11 +205,7 @@
 				cameraO.updateProjectionMatrix();
 				cameraO.updateProjectionMatrix();
 
 
 				renderer.setSize( width, height );
 				renderer.setSize( width, height );
-
-				var pixelRatio = renderer.getPixelRatio();
-				var newWidth = Math.floor( width / pixelRatio ) || 1;
-				var newHeight = Math.floor( height / pixelRatio ) || 1;
-				composer.setSize( newWidth, newHeight );
+				composer.setSize( width, height );
 
 
 			}
 			}
 
 

+ 8 - 11
examples/webgl_postprocessing_ssao.html

@@ -63,8 +63,7 @@
 
 
 			var container, stats;
 			var container, stats;
 			var camera, scene, renderer;
 			var camera, scene, renderer;
-			var effectComposer;
-			var ssaoPass;
+			var composer;
 			var group;
 			var group;
 
 
 			init();
 			init();
@@ -125,11 +124,11 @@
 				var width = window.innerWidth;
 				var width = window.innerWidth;
 				var height = window.innerHeight;
 				var height = window.innerHeight;
 
 
-				ssaoPass = new THREE.SSAOPass( scene, camera, width, height );
-				ssaoPass.kernelRadius = 16;
+				composer = new THREE.EffectComposer( renderer );
 
 
-				effectComposer = new THREE.EffectComposer( renderer );
-				effectComposer.addPass( ssaoPass );
+				var ssaoPass = new THREE.SSAOPass( scene, camera, width, height );
+				ssaoPass.kernelRadius = 16;
+				composer.addPass( ssaoPass );
 
 
 				// Init gui
 				// Init gui
 				var gui = new dat.GUI();
 				var gui = new dat.GUI();
@@ -152,8 +151,6 @@
 
 
 				window.addEventListener( 'resize', onWindowResize, false );
 				window.addEventListener( 'resize', onWindowResize, false );
 
 
-				onWindowResize();
-
 			}
 			}
 
 
 			function onWindowResize() {
 			function onWindowResize() {
@@ -163,9 +160,9 @@
 
 
 				camera.aspect = width / height;
 				camera.aspect = width / height;
 				camera.updateProjectionMatrix();
 				camera.updateProjectionMatrix();
-				renderer.setSize( width, height );
 
 
-				ssaoPass.setSize( width, height );
+				renderer.setSize( width, height );
+				composer.setSize( width, height );
 
 
 			}
 			}
 
 
@@ -185,7 +182,7 @@
 				group.rotation.x = timer * 0.0002;
 				group.rotation.x = timer * 0.0002;
 				group.rotation.y = timer * 0.0001;
 				group.rotation.y = timer * 0.0001;
 
 
-				effectComposer.render();
+				composer.render();
 
 
 			}
 			}
 
 

+ 1 - 5
examples/webgl_postprocessing_taa.html

@@ -172,11 +172,7 @@
 				camera.updateProjectionMatrix();
 				camera.updateProjectionMatrix();
 
 
 				renderer.setSize( width, height );
 				renderer.setSize( width, height );
-
-				var pixelRatio = renderer.getPixelRatio();
-				var newWidth = Math.floor( width / pixelRatio ) || 1;
-				var newHeight = Math.floor( height / pixelRatio ) || 1;
-				composer.setSize( newWidth, newHeight );
+				composer.setSize( width, height );
 
 
 			}
 			}
 
 

+ 0 - 1
examples/webgl_postprocessing_unreal_bloom.html

@@ -109,7 +109,6 @@
 			bloomPass.radius = params.bloomRadius;
 			bloomPass.radius = params.bloomRadius;
 
 
 			composer = new THREE.EffectComposer( renderer );
 			composer = new THREE.EffectComposer( renderer );
-			composer.setSize( window.innerWidth, window.innerHeight );
 			composer.addPass( renderScene );
 			composer.addPass( renderScene );
 			composer.addPass( bloomPass );
 			composer.addPass( bloomPass );
 
 

+ 2 - 4
examples/webgl_postprocessing_unreal_bloom_selective.html

@@ -140,7 +140,6 @@
 
 
 			var bloomComposer = new THREE.EffectComposer( renderer );
 			var bloomComposer = new THREE.EffectComposer( renderer );
 			bloomComposer.renderToScreen = false;
 			bloomComposer.renderToScreen = false;
-			bloomComposer.setSize( window.innerWidth * window.devicePixelRatio, window.innerHeight * window.devicePixelRatio );
 			bloomComposer.addPass( renderScene );
 			bloomComposer.addPass( renderScene );
 			bloomComposer.addPass( bloomPass );
 			bloomComposer.addPass( bloomPass );
 
 
@@ -158,7 +157,6 @@
 			finalPass.needsSwap = true;
 			finalPass.needsSwap = true;
 
 
 			var finalComposer = new THREE.EffectComposer( renderer );
 			var finalComposer = new THREE.EffectComposer( renderer );
-			finalComposer.setSize( window.innerWidth * window.devicePixelRatio, window.innerHeight * window.devicePixelRatio );
 			finalComposer.addPass( renderScene );
 			finalComposer.addPass( renderScene );
 			finalComposer.addPass( finalPass );
 			finalComposer.addPass( finalPass );
 
 
@@ -251,8 +249,8 @@
 
 
 				renderer.setSize( width, height );
 				renderer.setSize( width, height );
 
 
-				bloomComposer.setSize( width * window.devicePixelRatio, height * window.devicePixelRatio );
-				finalComposer.setSize( width * window.devicePixelRatio, height * window.devicePixelRatio );
+				bloomComposer.setSize( width, height );
+				finalComposer.setSize( width, height );
 
 
 				render();
 				render();
 
 

+ 2 - 3
examples/webgl_shader_lava.html

@@ -199,12 +199,11 @@
 
 
 			function onWindowResize() {
 			function onWindowResize() {
 
 
-				renderer.setSize( window.innerWidth, window.innerHeight );
-
 				camera.aspect = window.innerWidth / window.innerHeight;
 				camera.aspect = window.innerWidth / window.innerHeight;
 				camera.updateProjectionMatrix();
 				camera.updateProjectionMatrix();
 
 
-				composer.reset();
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				composer.setSize( window.innerWidth, window.innerHeight );
 
 
 			}
 			}
 
 

+ 4 - 0
files/ic_close_black_24dp.svg

@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="#000000">
+    <path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/>
+    <path d="M0 0h24v24H0z" fill="none"/>
+</svg>

+ 4 - 0
files/ic_code_black_24dp.svg

@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24" fill="#000000">
+    <path fill="none" d="M0 0h24v24H0V0z"/>
+    <path d="M9.4 16.6L4.8 12l4.6-4.6L8 6l-6 6 6 6 1.4-1.4zm5.2 0l4.6-4.6-4.6-4.6L16 6l6 6-6 6-1.4-1.4z"/>
+</svg>

+ 15 - 0
files/ic_github_black_24dp.svg

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="24px" height="24px" viewBox="0 0 24 24" enable-background="new 0 0 24 24" xml:space="preserve" fill="#000000">
+<g id="XMLID_399_">
+	<path id="XMLID_290_" fill-rule="evenodd" clip-rule="evenodd" d="M12,2C6.48,2,2,6.59,2,12.25c0,4.53,2.87,8.37,6.84,9.73
+		c0.5,0.09,0.68-0.22,0.68-0.49c0-0.24-0.01-0.89-0.01-1.74c-2.78,0.62-3.37-1.37-3.37-1.37c-0.45-1.18-1.11-1.5-1.11-1.5
+		c-0.91-0.64,0.07-0.62,0.07-0.62c1,0.07,1.53,1.06,1.53,1.06c0.89,1.57,2.34,1.11,2.91,0.85c0.09-0.66,0.35-1.11,0.63-1.37
+		c-2.22-0.26-4.56-1.14-4.56-5.07c0-1.12,0.39-2.03,1.03-2.75c-0.1-0.26-0.45-1.3,0.1-2.71c0,0,0.84-0.28,2.75,1.05
+		c0.8-0.23,1.65-0.34,2.5-0.34c0.85,0,1.7,0.12,2.5,0.34c1.91-1.33,2.75-1.05,2.75-1.05c0.55,1.41,0.2,2.45,0.1,2.71
+		c0.64,0.72,1.03,1.63,1.03,2.75c0,3.94-2.34,4.81-4.57,5.06c0.36,0.32,0.68,0.94,0.68,1.9c0,1.37-0.01,2.48-0.01,2.81
+		c0,0.27,0.18,0.59,0.69,0.49c3.97-1.36,6.83-5.2,6.83-9.73C22,6.59,17.52,2,12,2"/>
+	<rect id="XMLID_289_" fill-rule="evenodd" clip-rule="evenodd" fill="none" width="24" height="24"/>
+</g>
+</svg>

+ 165 - 85
files/main.css

@@ -1,6 +1,14 @@
+:root {
+	--color-blue: #049EF4;
+	--text-color: #444;
+	--border-style: 1px solid #EEE;
+	--header-height: 48px;
+	--panel-padding: 16px;
+}
+
 @font-face {
 @font-face {
-	font-family: 'RobotoMono';
-	src: local('RobotoMono'), url('../files/RobotoMono-Regular.woff2') format('woff2');
+	font-family: 'Roboto Mono';
+	src: local('Roboto Mono'), url('../files/RobotoMono-Regular.woff2') format('woff2');
 	font-weight: normal;
 	font-weight: normal;
 	font-style: normal;
 	font-style: normal;
 }
 }
@@ -16,13 +24,11 @@ html, body {
 body {
 body {
 	margin: 0px;
 	margin: 0px;
 	overflow: hidden;
 	overflow: hidden;
-
-	font-family: 'RobotoMono', monospace;
+	font-family: 'Roboto Mono', monospace;
 	font-size: 14px;
 	font-size: 14px;
-	line-height: 23px;
-
+	line-height: 24px;
 	background-color: #ffffff;
 	background-color: #ffffff;
-	color: #555;
+	color: var(--text-color);
 }
 }
 
 
 a {
 a {
@@ -30,107 +36,146 @@ a {
 }
 }
 
 
 h1 {
 h1 {
-	margin-top: 0px; /* reset */
-	margin-left: 15px;
-	margin-bottom: 20px;
-	padding-top: 13px;
-
 	font-size: 18px;
 	font-size: 18px;
-	font-weight: normal;
-}
-
-h1 a {
-	color: #049EF4;
+	font-weight: 500;
 }
 }
 
 
 h2 {
 h2 {
-	margin-top: 20px;
-
+	padding: 8px 0;
+	margin: 6px 0 12px 0;
 	font-size: 14px;
 	font-size: 14px;
 	font-weight: normal;
 	font-weight: normal;
-
-	color: #049EF4;
+	color: var(--color-blue);
 }
 }
 
 
 h3 {
 h3 {
-	margin: 20px 0 0 0;
-
+	margin: 4px 0;
 	font-size: 14px;
 	font-size: 14px;
 	line-height: 23px;
 	line-height: 23px;
 	font-weight: 500;
 	font-weight: 500;
 	text-transform: uppercase;
 	text-transform: uppercase;
-
 	color: #9E9E9E;
 	color: #9E9E9E;
 }
 }
 
 
+h1 a {
+	color: var(--color-blue);
+}
+
+#header {
+	display: flex;
+	height: 48px;
+	border-bottom: var(--border-style);
+	align-items: center;
+}
+#header h1 {
+	margin-left: 15px;
+	flex: 1;
+}
+
 #panel {
 #panel {
 	position: fixed;
 	position: fixed;
 	left: 0px;
 	left: 0px;
 	width: 300px;
 	width: 300px;
 	height: 100%;
 	height: 100%;
 	overflow: auto;
 	overflow: auto;
-
-	background: white;
-	border-right: 1px solid #f2f2f2;
+	border-right: var(--border-style);
+	display: flex;
+	flex-direction: column;
+	transition: 0s 0s height;
 }
 }
 
 
-	#panel #header {
-		position: -webkit-sticky;
-		position: sticky;
-		top: 0;
+	#panel #exitSearchButton {
+		position: absolute;
+		width: 40px;
+		height: 40px;
+		top: 4px;
+		right: calc(var(--panel-padding) - 12px);
+		z-index: 1000;
+		display: none;
+		background-size: 20px 20px;
+		background-position: 50% 50%;
+		background-repeat: no-repeat;
+		background-image: url(../files/ic_close_black_24dp.svg);
+		cursor: pointer;
+	}
 
 
-		background: white;
+	#panel.searchFocused #exitSearchButton {
+		display: block;
+	}
+
+	#panel.searchFocused #language {
+		display: none;
+	}
+
+	#panel.searchFocused #filter {
+		background-image: none;
+		padding-left: var(--panel-padding);
 	}
 	}
 
 
 	#panel #expandButton {
 	#panel #expandButton {
-		position: absolute;
-		right: 14px;
-		top: 14px;
+		margin-right: 14px;
+		margin-left: 4px;
 		display: none;
 		display: none;
 	}
 	}
 
 
 	#panel #sections {
 	#panel #sections {
-		font-size: 14px;
-		padding: 0px 16px;
+		font-weight: 500;
+		display: flex;
+		justify-content: center;
+		z-index: 1000;
+		position: relative;
+		height: 100%;
+		align-items: center;
 	}
 	}
 
 
 		#panel #sections * {
 		#panel #sections * {
-			display: inline-block;
-			margin-right: 35px;
-			margin-bottom: 12px;
-
-			font-weight: 500;
-
-			color: #333333;
+			padding: 0 var(--panel-padding);
+			height: 100%;
+			position: relative;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+		}
+		#panel #sections .selected:after {
+			content: "";
+			position: absolute;
+			left: 0;
+			right: 0;
+			bottom: -1px;
+			border-bottom: 1px solid black;
 		}
 		}
-
 		#panel #sections a {
 		#panel #sections a {
 			color: #9E9E9E;
 			color: #9E9E9E;
 		}
 		}
 
 
 	#panel #filter {
 	#panel #filter {
 		width: 100%;
 		width: 100%;
-		height: 40px;
-		padding: 0px 48px;
-		font-size: 15px;
+		height: 48px;
+		padding: 0px 44px;
+		font-weight: 500;
+		font-size: 14px;
+		color: var(--text-color);
 		outline: none;
 		outline: none;
-		border: 0px; /* reset */
-		border-top: 1px solid #f2f2f2;
-		border-bottom: 1px solid #f2f2f2;
-		background: url( "../files/ic_search_black_24dp.svg" ) no-repeat;
-		background-position: 14px center;
+		border: 0px;
+		border-bottom: var(--border-style);
+		background-size: 20px 20px;
+		background-image: url(../files/ic_search_black_24dp.svg);
+		background-position: 14px 50%;
+		background-repeat: no-repeat;
 	}
 	}
 
 
 	#panel #language {
 	#panel #language {
+		font-family: 'Roboto Mono', monospace;
 		position: absolute;
 		position: absolute;
-		top: 98px;
-		right: 14px;
+		top: 9px;
+		right: 8px;
 		border: 0px;
 		border: 0px;
 		font-size: 14px;
 		font-size: 14px;
-		background: url( "ic_arrow_drop_down_black_24dp.svg" ) no-repeat;
+		font-weight: 500;
+		background: url(ic_arrow_drop_down_black_24dp.svg) no-repeat;
 		background-position: right center;
 		background-position: right center;
 		background-color: white;
 		background-color: white;
-		padding: 4px 26px 4px 8px;
+		padding: 4px 24px 4px 8px;
 		-webkit-appearance: none;
 		-webkit-appearance: none;
 		-moz-appearance: none;
 		-moz-appearance: none;
 		appearance: none;
 		appearance: none;
@@ -140,26 +185,39 @@ h3 {
 			outline: none;
 			outline: none;
 		}
 		}
 
 
+	#contentWrapper {
+		flex: 1;
+		overflow: hidden;
+		display: flex;
+		flex-direction: column;
+		transform: translate3d(0,0,0);
+	}
 	#panel #content {
 	#panel #content {
-		margin: 0px 16px;
+		flex: 1;
+		overflow: scroll;
+		padding: 0 var(--panel-padding) 24px var(--panel-padding);
 	}
 	}
 
 
 		#panel #content ul {
 		#panel #content ul {
 			list-style-type: none;
 			list-style-type: none;
 			padding: 0px;
 			padding: 0px;
-			margin: 0px;
+			margin: 0px 0 24px 0;
+		}
+		#panel #content ul li {
+			margin: 2px 0;
 		}
 		}
 
 
 		#panel #content a {
 		#panel #content a {
-			color: #222222;
+			color: var(--text-color);
 		}
 		}
 
 
-			#panel #content a:hover {
-				text-decoration: underline;
-			}
+		#panel #content a:hover,
+		#panel #content .selected {
+			color: var(--color-blue);
+		}
 
 
 		#panel #content .selected {
 		#panel #content .selected {
-			color: #ff0000;
+			text-decoration: underline;
 		}
 		}
 
 
 		#panel #content .hidden {
 		#panel #content .hidden {
@@ -178,45 +236,67 @@ iframe {
 /* mobile */
 /* mobile */
 
 
 @media all and ( max-width: 640px ) {
 @media all and ( max-width: 640px ) {
-
+	#panel #expandButton {
+		display: block;
+	}
 	#panel {
 	#panel {
 		position: absolute;
 		position: absolute;
 		left: 0;
 		left: 0;
 		top: 0;
 		top: 0;
-		height: 100%;
 		width: 100%;
 		width: 100%;
 		right: 0;
 		right: 0;
 		z-index: 100;
 		z-index: 100;
-		border-bottom: 1px solid #dedede;
+		overflow-x: hidden;
+		transition: 0s 0s height;
+		border: none;
+		height: var(--header-height);
+		transition: 0s 0.2s height;
+	}
+	#panel.open {
+		height: 100%;
+		transition: 0s 0s height;
 	}
 	}
 
 
-		#panel #expandButton {
-			display: block;
-		}
-
-	/*
-	#navigation {
+	#panelScrim {
+		pointer-events: none;
+		background-color: rgba(0,0,0,0);
 		position: absolute;
 		position: absolute;
 		left: 0;
 		left: 0;
-		top: 90px;
 		right: 0;
 		right: 0;
+		top: 0;
 		bottom: 0;
 		bottom: 0;
-		font-size: 17px;
-		line-height: 22px;
-		overflow: auto;
+		z-index: 1000;
+		pointer-events: none;
+		transition: .2s background-color;
+	}
+	#panel.open #panelScrim {
+		pointer-events: auto;
+		background-color: rgba(0,0,0,0.4);
+	}
+
+	#contentWrapper {
+		position: absolute;
+		right: 0;
+		top: 0;
+		bottom: 0;
+		background: white;
+		box-shadow: 0 0 8px rgba(0,0,0,.1);
+		width: calc(100vw - 60px);
+		max-width: 360px;
+		z-index: 10000;
+		transition: .25s transform;
+		overflow-x: hidden;
+		margin-right: -380px;
+	}
+	#panel.open #contentWrapper {
+		transform: translate3d(-380px, 0 ,0);
 	}
 	}
-	*/
 
 
 	iframe {
 	iframe {
 		position: absolute;
 		position: absolute;
 		left: 0;
 		left: 0;
-		top: 92px;
+		top: var(--header-height);
 		width: 100%;
 		width: 100%;
-		height: calc(100% - 92px);
-	}
-
-	#panel.collapsed {
-		height: 92px;
+		height: calc(100% - var(--header-height));
 	}
 	}
-
 }
 }

+ 17 - 3
src/animation/AnimationAction.js

@@ -503,11 +503,19 @@ Object.assign( AnimationAction.prototype, {
 
 
 					time = 0;
 					time = 0;
 
 
-				} else break handle_stop;
+				} else {
+
+					this.time = time;
+
+					break handle_stop;
+
+				}
 
 
 				if ( this.clampWhenFinished ) this.paused = true;
 				if ( this.clampWhenFinished ) this.paused = true;
 				else this.enabled = false;
 				else this.enabled = false;
 
 
+				this.time = time;
+
 				this._mixer.dispatchEvent( {
 				this._mixer.dispatchEvent( {
 					type: 'finished', action: this,
 					type: 'finished', action: this,
 					direction: deltaTime < 0 ? - 1 : 1
 					direction: deltaTime < 0 ? - 1 : 1
@@ -559,6 +567,8 @@ Object.assign( AnimationAction.prototype, {
 
 
 					time = deltaTime > 0 ? duration : 0;
 					time = deltaTime > 0 ? duration : 0;
 
 
+					this.time = time;
+
 					this._mixer.dispatchEvent( {
 					this._mixer.dispatchEvent( {
 						type: 'finished', action: this,
 						type: 'finished', action: this,
 						direction: deltaTime > 0 ? 1 : - 1
 						direction: deltaTime > 0 ? 1 : - 1
@@ -583,26 +593,30 @@ Object.assign( AnimationAction.prototype, {
 
 
 					this._loopCount = loopCount;
 					this._loopCount = loopCount;
 
 
+					this.time = time;
+
 					this._mixer.dispatchEvent( {
 					this._mixer.dispatchEvent( {
 						type: 'loop', action: this, loopDelta: loopDelta
 						type: 'loop', action: this, loopDelta: loopDelta
 					} );
 					} );
 
 
 				}
 				}
 
 
+			} else {
+
+				this.time = time;
+
 			}
 			}
 
 
 			if ( pingPong && ( loopCount & 1 ) === 1 ) {
 			if ( pingPong && ( loopCount & 1 ) === 1 ) {
 
 
 				// invert time for the "pong round"
 				// invert time for the "pong round"
 
 
-				this.time = time;
 				return duration - time;
 				return duration - time;
 
 
 			}
 			}
 
 
 		}
 		}
 
 
-		this.time = time;
 		return time;
 		return time;
 
 
 	},
 	},

+ 11 - 0
src/core/BufferAttribute.js

@@ -319,6 +319,17 @@ Object.assign( BufferAttribute.prototype, {
 
 
 		return new this.constructor( this.array, this.itemSize ).copy( this );
 		return new this.constructor( this.array, this.itemSize ).copy( this );
 
 
+	},
+
+	toJSON: function () {
+
+		return {
+			itemSize: this.itemSize,
+			type: this.array.constructor.name,
+			array: Array.prototype.slice.call( this.array ),
+			normalized: this.normalized
+		};
+
 	}
 	}
 
 
 } );
 } );

+ 2 - 12
src/core/BufferGeometry.js

@@ -1063,12 +1063,7 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy
 
 
 			var attribute = attributes[ key ];
 			var attribute = attributes[ key ];
 
 
-			var attributeData = {
-				itemSize: attribute.itemSize,
-				type: attribute.array.constructor.name,
-				array: Array.prototype.slice.call( attribute.array ),
-				normalized: attribute.normalized
-			};
+			var attributeData = attribute.toJSON();
 
 
 			if ( attribute.name !== '' ) attributeData.name = attribute.name;
 			if ( attribute.name !== '' ) attributeData.name = attribute.name;
 
 
@@ -1089,12 +1084,7 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy
 
 
 				var attribute = attributeArray[ i ];
 				var attribute = attributeArray[ i ];
 
 
-				var attributeData = {
-					itemSize: attribute.itemSize,
-					type: attribute.array.constructor.name,
-					array: Array.prototype.slice.call( attribute.array ),
-					normalized: attribute.normalized
-				};
+				var attributeData = attribute.toJSON();
 
 
 				if ( attribute.name !== '' ) attributeData.name = attribute.name;
 				if ( attribute.name !== '' ) attributeData.name = attribute.name;
 
 

+ 12 - 0
src/core/InstancedBufferAttribute.js

@@ -36,6 +36,18 @@ InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribu
 
 
 		return this;
 		return this;
 
 
+	},
+
+	toJSON: function ()	{
+
+		var data = BufferAttribute.prototype.toJSON.call( this );
+
+		data.meshPerAttribute = this.meshPerAttribute;
+
+		data.isInstancedBufferAttribute = true;
+
+		return data;
+
 	}
 	}
 
 
 } );
 } );

+ 1 - 0
src/geometries/ExtrudeGeometry.d.ts

@@ -13,6 +13,7 @@ export interface ExtrudeGeometryOptions {
   bevelEnabled?: boolean;
   bevelEnabled?: boolean;
   bevelThickness?: number;
   bevelThickness?: number;
   bevelSize?: number;
   bevelSize?: number;
+  bevelOffset?: number;
   bevelSegments?: number;
   bevelSegments?: number;
   extrudePath?: CurvePath<Vector3>;
   extrudePath?: CurvePath<Vector3>;
   UVGenerator?: UVGenerator;
   UVGenerator?: UVGenerator;

+ 3 - 0
src/geometries/TextGeometry.d.ts

@@ -10,6 +10,7 @@ export interface TextGeometryParameters {
   bevelEnabled?: boolean;
   bevelEnabled?: boolean;
   bevelThickness?: number;
   bevelThickness?: number;
   bevelSize?: number;
   bevelSize?: number;
+  bevelOffset?: number;
   bevelSegments?: number;
   bevelSegments?: number;
 }
 }
 
 
@@ -24,6 +25,7 @@ export class TextBufferGeometry extends ExtrudeBufferGeometry {
     bevelEnabled: boolean;
     bevelEnabled: boolean;
     bevelThickness: number;
     bevelThickness: number;
     bevelSize: number;
     bevelSize: number;
+    bevelOffset: number;
     bevelSegments: number;
     bevelSegments: number;
   };
   };
 }
 }
@@ -39,6 +41,7 @@ export class TextGeometry extends ExtrudeGeometry {
     bevelEnabled: boolean;
     bevelEnabled: boolean;
     bevelThickness: number;
     bevelThickness: number;
     bevelSize: number;
     bevelSize: number;
+    bevelOffset: number;
     bevelSegments: number;
     bevelSegments: number;
   };
   };
 }
 }

+ 1 - 0
src/materials/Material.d.ts

@@ -44,6 +44,7 @@ export interface MaterialParameters {
   dithering?: boolean;
   dithering?: boolean;
   flatShading?: boolean;
   flatShading?: boolean;
   side?: Side;
   side?: Side;
+	shadowSide?: Side;
   transparent?: boolean;
   transparent?: boolean;
   vertexColors?: Colors;
   vertexColors?: Colors;
   vertexTangents?: boolean;
   vertexTangents?: boolean;

+ 1 - 1
src/renderers/WebGLRenderer.js

@@ -84,7 +84,7 @@ function WebGLRenderer( parameters ) {
 		 * Enables error checking and reporting when shader programs are being compiled
 		 * Enables error checking and reporting when shader programs are being compiled
 		 * @type {boolean}
 		 * @type {boolean}
 		 */
 		 */
-		checkShaderErrors: false
+		checkShaderErrors: true
 	};
 	};
 
 
 	// clearing
 	// clearing

+ 9 - 0
src/renderers/webgl/WebGLAnimation.d.ts

@@ -0,0 +1,9 @@
+export class WebGLAnimation {
+	start(): void;
+
+	stop(): void;
+
+	setAnimationLoop(callback: Function): void;
+
+	setContext(value: CanvasRenderingContext2D | WebGLRenderingContext): void;
+}

+ 9 - 0
src/renderers/webgl/WebGLAttributes.d.ts

@@ -0,0 +1,9 @@
+export class WebGLAttributes {
+	constructor(gl: CanvasRenderingContext2D | WebGLRenderingContext);
+
+	get(attribute: any): any;
+
+	remove(attribute: any): void;
+
+	update(attribute: any, bufferType: Array): void;
+}

+ 2 - 0
src/renderers/webvr/WebVRManager.js

@@ -153,6 +153,8 @@ function WebVRManager( renderer ) {
 
 
 				var buttonId = gamepad.id === 'Daydream Controller' ? 0 : 1;
 				var buttonId = gamepad.id === 'Daydream Controller' ? 0 : 1;
 
 
+				if ( triggers[ i ] === undefined ) triggers[ i ] = false;
+
 				if ( triggers[ i ] !== gamepad.buttons[ buttonId ].pressed ) {
 				if ( triggers[ i ] !== gamepad.buttons[ buttonId ].pressed ) {
 
 
 					triggers[ i ] = gamepad.buttons[ buttonId ].pressed;
 					triggers[ i ] = gamepad.buttons[ buttonId ].pressed;

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