Просмотр исходного кода

Merge pull request #12 from mrdoob/dev

Update
Temdog007 6 лет назад
Родитель
Сommit
fa398a1cb7
58 измененных файлов с 1301 добавлено и 728 удалено
  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 ) {
 
+		var renderWidth, renderHeight;
 		var scope = this;
 
 		var device = null;
@@ -21998,11 +21999,11 @@
 		var tempPosition = new Vector3();
 
 		var cameraL = new PerspectiveCamera();
-		cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 );
+		cameraL.viewport = new Vector4();
 		cameraL.layers.enable( 1 );
 
 		var cameraR = new PerspectiveCamera();
-		cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 );
+		cameraR.viewport = new Vector4();
 		cameraR.layers.enable( 2 );
 
 		var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
@@ -22024,14 +22025,17 @@
 			if ( isPresenting() ) {
 
 				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();
 				renderer.getSize( currentSize );
 
 				renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 );
 
+				cameraL.viewport.set( 0, 0, renderWidth, renderHeight );
+				cameraR.viewport.set( renderWidth, 0, renderWidth, renderHeight );
+
 				animation.start();
 
 			} 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;
@@ -22299,17 +22313,8 @@
 
 				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
 			 * @type {boolean}
 			 */
-			checkShaderErrors: false
+			checkShaderErrors: true
 		};
 
 		// clearing
@@ -23998,22 +24003,7 @@
 
 						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 );
 
@@ -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;
 
-					} else break handle_stop;
+					} else {
+
+						this.time = time;
+
+						break handle_stop;
+
+					}
 
 					if ( this.clampWhenFinished ) this.paused = true;
 					else this.enabled = false;
 
+					this.time = time;
+
 					this._mixer.dispatchEvent( {
 						type: 'finished', action: this,
 						direction: deltaTime < 0 ? - 1 : 1
@@ -43300,6 +43307,8 @@
 
 						time = deltaTime > 0 ? duration : 0;
 
+						this.time = time;
+
 						this._mixer.dispatchEvent( {
 							type: 'finished', action: this,
 							direction: deltaTime > 0 ? 1 : - 1
@@ -43324,26 +43333,30 @@
 
 						this._loopCount = loopCount;
 
+						this.time = time;
+
 						this._mixer.dispatchEvent( {
 							type: 'loop', action: this, loopDelta: loopDelta
 						} );
 
 					}
 
+				} else {
+
+					this.time = time;
+
 				}
 
 				if ( pingPong && ( loopCount & 1 ) === 1 ) {
 
 					// invert time for the "pong round"
 
-					this.time = time;
 					return duration - time;
 
 				}
 
 			}
 
-			this.time = time;
 			return time;
 
 		},

Разница между файлами не показана из-за своего большого размера
+ 68 - 293
build/three.min.js


+ 50 - 37
build/three.module.js

@@ -21965,6 +21965,7 @@ function setProjectionFromUnion( camera, cameraL, cameraR ) {
 
 function WebVRManager( renderer ) {
 
+	var renderWidth, renderHeight;
 	var scope = this;
 
 	var device = null;
@@ -21992,11 +21993,11 @@ function WebVRManager( renderer ) {
 	var tempPosition = new Vector3();
 
 	var cameraL = new PerspectiveCamera();
-	cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 );
+	cameraL.viewport = new Vector4();
 	cameraL.layers.enable( 1 );
 
 	var cameraR = new PerspectiveCamera();
-	cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 );
+	cameraR.viewport = new Vector4();
 	cameraR.layers.enable( 2 );
 
 	var cameraVR = new ArrayCamera( [ cameraL, cameraR ] );
@@ -22018,14 +22019,17 @@ function WebVRManager( renderer ) {
 		if ( isPresenting() ) {
 
 			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();
 			renderer.getSize( currentSize );
 
 			renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 );
 
+			cameraL.viewport.set( 0, 0, renderWidth, renderHeight );
+			cameraR.viewport.set( renderWidth, 0, renderWidth, renderHeight );
+
 			animation.start();
 
 		} 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;
@@ -22293,17 +22307,8 @@ function WebVRManager( renderer ) {
 
 			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
 		 * @type {boolean}
 		 */
-		checkShaderErrors: false
+		checkShaderErrors: true
 	};
 
 	// clearing
@@ -23992,22 +23997,7 @@ function WebGLRenderer( parameters ) {
 
 					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 );
 
@@ -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;
 
-				} else break handle_stop;
+				} else {
+
+					this.time = time;
+
+					break handle_stop;
+
+				}
 
 				if ( this.clampWhenFinished ) this.paused = true;
 				else this.enabled = false;
 
+				this.time = time;
+
 				this._mixer.dispatchEvent( {
 					type: 'finished', action: this,
 					direction: deltaTime < 0 ? - 1 : 1
@@ -43294,6 +43301,8 @@ Object.assign( AnimationAction.prototype, {
 
 					time = deltaTime > 0 ? duration : 0;
 
+					this.time = time;
+
 					this._mixer.dispatchEvent( {
 						type: 'finished', action: this,
 						direction: deltaTime > 0 ? 1 : - 1
@@ -43318,26 +43327,30 @@ Object.assign( AnimationAction.prototype, {
 
 					this._loopCount = loopCount;
 
+					this.time = time;
+
 					this._mixer.dispatchEvent( {
 						type: 'loop', action: this, loopDelta: loopDelta
 					} );
 
 				}
 
+			} else {
+
+				this.time = time;
+
 			}
 
 			if ( pingPong && ( loopCount & 1 ) === 1 ) {
 
 				// invert time for the "pong round"
 
-				this.time = time;
 				return duration - time;
 
 			}
 
 		}
 
-		this.time = time;
 		return time;
 
 	},

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

@@ -425,7 +425,7 @@
 
 		<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>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>
 		<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>
 	</head>
 	<body>
-
-		<div id="panel" class="collapsed">
+		<div id="panel" class="">
 
 			<div id="header">
-
 				<h1><a href="http://threejs.org">three.js</a></h1>
 
-				<img id="expandButton" src="../files/ic_menu_black_24dp.svg">
-
 				<div id="sections">
-					<span class="selected">docs</span> <a href="../examples/">examples</a>
+					<span class="selected">docs</span>
+					<a href="../examples/">examples</a>
 				</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">
 					<option value="en">en</option>
 					<option value="zh">zh</option>
 				</select>
 
+				<div id="content"></div>
 			</div>
 
-			<div id="content"></div>
-
 		</div>
 
 		<iframe name="viewer"></iframe>
@@ -89,6 +92,8 @@
 			var panel = document.getElementById( 'panel' );
 			var content = document.getElementById( 'content' );
 			var expandButton = document.getElementById( 'expandButton' );
+			var exitSearchButton = document.getElementById( 'exitSearchButton' );
+			var panelScrim = document.getElementById( 'panelScrim' );
 			var filterInput = document.getElementById( 'filter' );
 			var iframe = document.querySelector( 'iframe' );
 
@@ -104,12 +109,40 @@
 			expandButton.onclick = function ( event ) {
 
 				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
+			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 ) {
 
@@ -139,7 +172,16 @@
 					if ( event.button !== 0 || event.ctrlKey || event.altKey || event.metaKey ) return;
 
 					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>
 
-		<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>
 			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>
 			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
 			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.

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

@@ -25,7 +25,7 @@
 
 		<h2>Help forums</h2>
 		<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.
 		</p>
 
@@ -46,6 +46,9 @@
 
 		<h3>More extensive / advanced articles and courses</h3>
 		<ul>
+			<li>
+				[link:https://discoverthreejs.com/ Discover three.js]
+			</li>
 			<li>
 				[link:https://threejsfundamentals.org/ Three.js Fundamentals]
 			</li>
@@ -66,21 +69,16 @@
 			 [link:http://learningthreejs.com/ Learning Three.js] – a blog with articles dedicated to teaching three.js
 		 </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>
 		</ul>
 
-		<h3>Tutorials in other languages</h3>
+		<h2>News and Updates</h2>
 		<ul>
 			<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>
-
-		</ul>
-
-		<h2>News and Updates</h2>
-		<ul>
 			<li>
 				[link:http://www.reddit.com/r/threejs/ Three.js on reddit]
 			</li>
@@ -90,9 +88,6 @@
 			<li>
 				[link:http://learningwebgl.com/blog/ Learning WebGL Blog] – The authoritive news source for WebGL.
 			</li>
-			<li>
-				[link:https://plus.google.com/104300307601542851567/posts Three.js posts] on Google+ – frequent posts on Three.js
-			</li>
 		</ul>
 
 		<h2>Examples</h2>
@@ -179,6 +174,13 @@
 			[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]
 		</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>
 
 	</body>

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

@@ -31,6 +31,9 @@
 
 		<h3>three.js入门</h3>
 		<ul>
+			<li>
+				[link:https://threejsfundamentals.org/threejs/lessons/threejs-fundamentals.html Three.js Fundamentals starting lesson]
+			</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].
 			</li>
@@ -41,6 +44,12 @@
 
 		<h3>更加广泛、高级的文章与教程</h3>
 		<ul>
+			<li>
+				[link:https://discoverthreejs.com/ Discover three.js]
+			</li>
+			<li>
+				[link:https://threejsfundamentals.org/ Three.js Fundamentals]
+			</li>
 			<li>
 				[link:http://blog.cjgammon.com/ Collection of tutorials] by [link:http://www.cjgammon.com/ CJ Gammon].
 			</li>
@@ -58,21 +67,16 @@
 			 [link:http://learningthreejs.com/ Learning Three.js] – a blog with articles dedicated to teaching three.js
 		 </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>
 		</ul>
 
-		<h3>其它非英语的教程</h3>
+		<h2>新闻与更新</h2>
 		<ul>
 			<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>
-
-		</ul>
-
-		<h2>新闻与更新</h2>
-		<ul>
 			<li>
 				[link:http://www.reddit.com/r/threejs/ Three.js on reddit]
 			</li>
@@ -82,9 +86,6 @@
 			<li>
 				[link:http://learningwebgl.com/blog/ Learning WebGL Blog] – The authoritive news source for WebGL.
 			</li>
-			<li>
-				[link:https://plus.google.com/104300307601542851567/posts Three.js posts] on Google+ – frequent posts on Three.js
-			</li>
 		</ul>
 		<h2>示例</h2>
 		<ul>
@@ -165,6 +166,13 @@
 			[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]
 		</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>
 
 	</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-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-style: normal;
 }
@@ -13,54 +20,86 @@
 }
 
 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-size: 16px;
-	line-height: 23px;
+	line-height: 24px;
 	tab-size: 4;
 	overflow: auto;
 }
 
 a {
-	color: #1184CE;
+	color: var(--color-blue);
 	cursor: pointer;
-	text-decoration: underline;
+	text-decoration: none;
 }
 
 h1 {
-	color: #049EF4;
-	font-size: 32px;
+	color: var(--color-blue);
+	font-size: 2.4em;
 	font-weight: normal;
-	line-height: 42px;
+	line-height: 1.36em;
+	margin-top: 16px;
+	margin-bottom: -16px;
+	text-indent: -2px;
 }
 
 h2 {
-	color: #4B0;
-
-	font-size: 22px;
+	color: var(--color-blue);
+	font-size: 1.8em;
+	line-height: 1.32em;
 	font-weight: normal;
-	line-height: 31px;
+	margin-top: 40px;
+	margin-bottom: 12px;
+	text-indent: -1px;
 }
 
 h3 {
-	color: #000;
-	font-size: 16px;
+	font-size: 1.32em;
+	line-height: 1.48em;
 	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;
-	max-width: 780px;
 }
 
 div {
-	/* padding-left: 30px; */
 	margin-bottom: 20px;
 }
 
@@ -68,17 +107,30 @@ div {
 	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 {
 	display: block;
-	padding: 20px;
+	padding: 20px 24px;
 	white-space: pre-wrap;
-	background-color: #f9f9f9;
 	overflow: auto;
+	box-sizing: border-box;
 }
 
 iframe {
@@ -109,15 +161,15 @@ strong {
 
 #button {
 	position: fixed;
-	bottom: 16px;
-	right: 16px;
+	bottom: 12px;
+	right: 12px;
 
 	padding: 8px;
 	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 {
@@ -127,6 +179,7 @@ strong {
 
 	#button img {
 		display: block;
+		width: 20px;
 	}
 
 a.permalink {
@@ -157,19 +210,17 @@ sub {
 /* mobile */
 
 @media all and ( max-width: 640px ) {
-
 	body {
-		margin: 14px auto;
-		padding: 0px 14px;
-		font-size: 14px;
-		line-height: 22px;
+		padding: 16px 20px;
 	}
 
 	h1 {
+		margin-top: 0;
 		font-size: 26px;
 	}
 
 	h2 {
+		margin-top: 20px;
 		font-size: 18px;
 		line-height: 25px;
 	}

+ 2 - 2
docs/prettify/threejs.css

@@ -11,7 +11,7 @@ pre .dec, code .dec { color: #22c0c4; } /* decimal */
 
 pre.prettyprint, code.prettyprint {
 	background-color: #F5F5F5;
-	font-family: 'RobotoMono', monospace;
+	font-family: 'Roboto Mono', monospace;
 	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",
+  "short_name": "Three.js",
+  "start_url": ".",
+  "scope": ".",
+  "display": "standalone",
   "icons": [
     {
       "src": "./images/icon.png",
       "type": "image/png",
       "sizes": "144x144"
     }
-  ],
-  "start_url": ".",
-  "display": "standalone"
+  ]
 }

+ 2 - 2
examples/css3d_panorama_deviceorientation.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html>
 	<head>
-		<title>three.js css3d - panorama - deviceorientation</title>
+		<title>three.js css3d - panorama - device orientation</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<style>
@@ -34,7 +34,7 @@
 		<script src="js/controls/DeviceOrientationControls.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>
 

+ 1 - 0
examples/files.js

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

+ 66 - 24
examples/index.html

@@ -9,24 +9,29 @@
 		<style>
 			#panel #content .link {
 				display: block;
-				text-decoration: none;
-				cursor: pointer;
 			}
-
-			#viewSrcButton {
+			#button {
 				position: fixed;
-				bottom: 20px;
-				right: 20px;
+				bottom: 12px;
+				right: 12px;
+
 				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;
 				opacity: 1;
 			}
+
+			#button img {
+				display: block;
+				width: 20px;
+			}
 		</style>
 	</head>
 	<body>
@@ -34,25 +39,36 @@
 		<div id="panel">
 
 			<div id="header">
-
 				<h1><a href="http://threejs.org">three.js</a></h1>
 
-				<img id="expandButton" src="../files/ic_menu_black_24dp.svg">
-
 				<div id="sections">
-					<a href="../docs/">docs</a> <span class="selected">examples</span>
+					<a href="../docs/">docs</a>
+					<span class="selected">examples</span>
 				</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="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>
 
 		<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>
@@ -70,13 +86,22 @@
 		var viewer = document.getElementById( 'viewer' );
 
 		var filterInput = document.getElementById( 'filter' );
+		var exitSearchButton = document.getElementById( 'exitSearchButton' );
 
 		var expandButton = document.getElementById( 'expandButton' );
 		expandButton.addEventListener( 'click', function ( event ) {
 			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
 
 		if ( /(iPad|iPhone|iPod)/g.test( navigator.userAgent ) ) {
@@ -90,12 +115,8 @@
 		var container = document.createElement( 'div' );
 		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';
-		document.body.appendChild( viewSrcButton );
 
 		var links = {};
 		var selected = null;
@@ -157,7 +178,7 @@
 			window.location.hash = file;
 			viewer.focus();
 
-			panel.classList.add( 'collapsed' );
+			panel.classList.remove( 'open' );
 
 			selected = file;
 
@@ -175,6 +196,27 @@
 		}
 
 		// 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 ) {
 

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

@@ -1740,7 +1740,12 @@ THREE.GLTFExporter.prototype = {
 
 			} 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 ] ) ) {
 
 					gltfNode.matrix = object.matrix.elements;

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

@@ -72,7 +72,7 @@ THREE.ThreeMFLoader.prototype = {
 
 			for ( file in zip.files ) {
 
-				if ( file.match( /\.rels$/ ) ) {
+				if ( file.match( /\_rels\/.rels$/ ) ) {
 
 					relsName = file;
 
@@ -206,9 +206,38 @@ THREE.ThreeMFLoader.prototype = {
 		}
 
 		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 = {};
 
@@ -300,6 +329,59 @@ THREE.ThreeMFLoader.prototype = {
 
 		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 ) {
@@ -383,7 +465,7 @@ THREE.ThreeMFLoader.prototype = {
 
 			if ( basematerialsNode ) {
 
-				resourcesData[ 'basematerial' ] = parseBasematerialsNode( basematerialsNode );
+				resourcesData[ 'basematerials' ] = parseBasematerialsNode( basematerialsNode );
 
 			}
 
@@ -411,25 +493,13 @@ THREE.ThreeMFLoader.prototype = {
 
 				var itemNode = itemNodes[ i ];
 				var buildItem = {
-					objectid: itemNode.getAttribute( 'objectid' )
+					objectId: itemNode.getAttribute( 'objectid' )
 				};
 				var transform = itemNode.getAttribute( '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();
 			geometry.setIndex( new THREE.BufferAttribute( meshData[ 'triangles' ], 1 ) );
 			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();
 
-			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 {
 
-				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 );
 
 		}
 
-		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 ) {
 
@@ -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 meshes = {};
+			var objects = {};
 			var modelsKeys = Object.keys( modelsData );
 
 			for ( var i = 0; i < modelsKeys.length; i ++ ) {
 
 				var modelsKey = modelsKeys[ i ];
 				var modelData = modelsData[ modelsKey ];
-				var modelXml = modelData[ 'xml' ];
-				var extensions = modelData[ 'extensions' ];
 
 				var objectIds = Object.keys( modelData[ 'resources' ][ 'object' ] );
 
 				for ( var j = 0; j < objectIds.length; 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 buildData = data3mf.model[ refs[ 'target' ].substring( 1 ) ][ 'build' ];
@@ -582,15 +877,19 @@ THREE.ThreeMFLoader.prototype = {
 			for ( var i = 0; i < buildData.length; 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 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 ++ ) {
 
-					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' ) {
 
-				object.userData = gltfDef.extras;
+				Object.assign( object.userData, gltfDef.extras );
 
 			} else {
 
@@ -2996,6 +2997,7 @@ THREE.GLTFLoader = ( function () {
 
 			if ( nodeDef.name !== undefined ) {
 
+				node.userData.name = 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
 		};
 
-		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';
 
+	} else {
+
+		this._pixelRatio = 1;
+		this._width = renderTarget.width;
+		this._height = renderTarget.height;
+
 	}
 
 	this.renderTarget1 = renderTarget;
@@ -162,10 +172,13 @@ Object.assign( THREE.EffectComposer.prototype, {
 
 		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.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 ) {
 
-		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 ++ ) {
 
-			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_WIDTH = window.innerWidth;
 
-				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
-
 				camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
 				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


Разница между файлами не показана из-за своего большого размера
+ 0 - 10
examples/textures/miranda_uncropped.hdr


+ 5 - 5
examples/webgl_buffergeometry_lines.html

@@ -50,7 +50,7 @@
 
 			var camera, scene, renderer;
 
-			var mesh;
+			var line;
 
 			init();
 			animate();
@@ -99,8 +99,8 @@
 
 				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;
 
-				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 );
 

+ 5 - 5
examples/webgl_buffergeometry_lines_indexed.html

@@ -50,7 +50,7 @@
 
 			var camera, scene, renderer;
 
-			var mesh, parent_node;
+			var parent_node;
 
 			init();
 			animate();
@@ -201,12 +201,12 @@
 				geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
 				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.add( mesh );
+				parent_node.add( lineSegments );
 
 				scene.add( parent_node );
 

+ 6 - 6
examples/webgl_custom_attributes_lines.html

@@ -83,7 +83,7 @@
 
 		var renderer, scene, camera, stats;
 
-		var object, uniforms;
+		var line, uniforms;
 
 		var loader = new THREE.FontLoader();
 		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.setPixelRatio( window.devicePixelRatio );
@@ -197,12 +197,12 @@
 
 			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.color.value.offsetHSL( 0.0005, 0, 0 );
 
-			var attributes = object.geometry.attributes;
+			var attributes = line.geometry.attributes;
 			var array = attributes.displacement.array;
 
 			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>
 
 		<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>
 
 		<script src="../build/three.js"></script>
@@ -51,7 +52,7 @@
 			}
 
 			var params = {
-				exposure: 1.0
+				exposure: 2.0
 			};
 
 			var renderer, scene, camera;
@@ -76,7 +77,7 @@
 
 				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( texture );
@@ -92,7 +93,7 @@
 
 					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 );
 
@@ -106,7 +107,7 @@
 
 				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();
 
 				//

+ 6 - 5
examples/webgl_loader_texture_hdr.html

@@ -32,7 +32,8 @@
 	<body>
 
 		<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>
 
 		<script src="../build/three.js"></script>
@@ -51,7 +52,7 @@
 			}
 
 			var params = {
-				exposure: 1.0
+				exposure: 2.0
 			};
 
 			var renderer, scene, camera;
@@ -76,7 +77,7 @@
 
 				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( texture );
@@ -88,7 +89,7 @@
 
 					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 );
 
@@ -102,7 +103,7 @@
 
 				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();
 
 				//

+ 1 - 1
examples/webgl_materials_video.html

@@ -244,7 +244,7 @@
 				camera.updateProjectionMatrix();
 
 				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.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 );
 
@@ -156,17 +156,16 @@
 
 			function onWindowResize() {
 
-				renderer.setSize( window.innerWidth, window.innerHeight );
-
 				camera.aspect = window.innerWidth / window.innerHeight;
 				camera.updateProjectionMatrix();
 
 				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();*/
 
 				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;
 
 			init();
@@ -45,7 +45,7 @@
 
 			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;
 
 				var scene1 = new THREE.Scene();
@@ -101,6 +101,21 @@
 				composer.addPass( clearMaskPass );
 				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() {

+ 1 - 5
examples/webgl_postprocessing_smaa.html

@@ -92,11 +92,7 @@
 				camera.updateProjectionMatrix();
 
 				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
 
 				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 );
 
 				var controls = new THREE.OrbitControls( camera, renderer.domElement );
@@ -145,8 +145,8 @@
 				renderer.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();
 
 				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
 
 				composer = new THREE.EffectComposer( renderer );
+				composer.setPixelRatio( 1 ); // ensure pixel ratio is always 1 for performance reasons
 				ssaaRenderPassP = new THREE.SSAARenderPass( scene, cameraP );
 				composer.addPass( ssaaRenderPassP );
 				ssaaRenderPassO = new THREE.SSAARenderPass( scene, cameraO );
@@ -204,11 +205,7 @@
 				cameraO.updateProjectionMatrix();
 
 				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 camera, scene, renderer;
-			var effectComposer;
-			var ssaoPass;
+			var composer;
 			var group;
 
 			init();
@@ -125,11 +124,11 @@
 				var width = window.innerWidth;
 				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
 				var gui = new dat.GUI();
@@ -152,8 +151,6 @@
 
 				window.addEventListener( 'resize', onWindowResize, false );
 
-				onWindowResize();
-
 			}
 
 			function onWindowResize() {
@@ -163,9 +160,9 @@
 
 				camera.aspect = width / height;
 				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.y = timer * 0.0001;
 
-				effectComposer.render();
+				composer.render();
 
 			}
 

+ 1 - 5
examples/webgl_postprocessing_taa.html

@@ -172,11 +172,7 @@
 				camera.updateProjectionMatrix();
 
 				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;
 
 			composer = new THREE.EffectComposer( renderer );
-			composer.setSize( window.innerWidth, window.innerHeight );
 			composer.addPass( renderScene );
 			composer.addPass( bloomPass );
 

+ 2 - 4
examples/webgl_postprocessing_unreal_bloom_selective.html

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

+ 2 - 3
examples/webgl_shader_lava.html

@@ -199,12 +199,11 @@
 
 			function onWindowResize() {
 
-				renderer.setSize( window.innerWidth, window.innerHeight );
-
 				camera.aspect = window.innerWidth / window.innerHeight;
 				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-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-style: normal;
 }
@@ -16,13 +24,11 @@ html, body {
 body {
 	margin: 0px;
 	overflow: hidden;
-
-	font-family: 'RobotoMono', monospace;
+	font-family: 'Roboto Mono', monospace;
 	font-size: 14px;
-	line-height: 23px;
-
+	line-height: 24px;
 	background-color: #ffffff;
-	color: #555;
+	color: var(--text-color);
 }
 
 a {
@@ -30,107 +36,146 @@ a {
 }
 
 h1 {
-	margin-top: 0px; /* reset */
-	margin-left: 15px;
-	margin-bottom: 20px;
-	padding-top: 13px;
-
 	font-size: 18px;
-	font-weight: normal;
-}
-
-h1 a {
-	color: #049EF4;
+	font-weight: 500;
 }
 
 h2 {
-	margin-top: 20px;
-
+	padding: 8px 0;
+	margin: 6px 0 12px 0;
 	font-size: 14px;
 	font-weight: normal;
-
-	color: #049EF4;
+	color: var(--color-blue);
 }
 
 h3 {
-	margin: 20px 0 0 0;
-
+	margin: 4px 0;
 	font-size: 14px;
 	line-height: 23px;
 	font-weight: 500;
 	text-transform: uppercase;
-
 	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 {
 	position: fixed;
 	left: 0px;
 	width: 300px;
 	height: 100%;
 	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 {
-		position: absolute;
-		right: 14px;
-		top: 14px;
+		margin-right: 14px;
+		margin-left: 4px;
 		display: none;
 	}
 
 	#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 * {
-			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 {
 			color: #9E9E9E;
 		}
 
 	#panel #filter {
 		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;
-		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 {
+		font-family: 'Roboto Mono', monospace;
 		position: absolute;
-		top: 98px;
-		right: 14px;
+		top: 9px;
+		right: 8px;
 		border: 0px;
 		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-color: white;
-		padding: 4px 26px 4px 8px;
+		padding: 4px 24px 4px 8px;
 		-webkit-appearance: none;
 		-moz-appearance: none;
 		appearance: none;
@@ -140,26 +185,39 @@ h3 {
 			outline: none;
 		}
 
+	#contentWrapper {
+		flex: 1;
+		overflow: hidden;
+		display: flex;
+		flex-direction: column;
+		transform: translate3d(0,0,0);
+	}
 	#panel #content {
-		margin: 0px 16px;
+		flex: 1;
+		overflow: scroll;
+		padding: 0 var(--panel-padding) 24px var(--panel-padding);
 	}
 
 		#panel #content ul {
 			list-style-type: none;
 			padding: 0px;
-			margin: 0px;
+			margin: 0px 0 24px 0;
+		}
+		#panel #content ul li {
+			margin: 2px 0;
 		}
 
 		#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 {
-			color: #ff0000;
+			text-decoration: underline;
 		}
 
 		#panel #content .hidden {
@@ -178,45 +236,67 @@ iframe {
 /* mobile */
 
 @media all and ( max-width: 640px ) {
-
+	#panel #expandButton {
+		display: block;
+	}
 	#panel {
 		position: absolute;
 		left: 0;
 		top: 0;
-		height: 100%;
 		width: 100%;
 		right: 0;
 		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;
 		left: 0;
-		top: 90px;
 		right: 0;
+		top: 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 {
 		position: absolute;
 		left: 0;
-		top: 92px;
+		top: var(--header-height);
 		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;
 
-				} else break handle_stop;
+				} else {
+
+					this.time = time;
+
+					break handle_stop;
+
+				}
 
 				if ( this.clampWhenFinished ) this.paused = true;
 				else this.enabled = false;
 
+				this.time = time;
+
 				this._mixer.dispatchEvent( {
 					type: 'finished', action: this,
 					direction: deltaTime < 0 ? - 1 : 1
@@ -559,6 +567,8 @@ Object.assign( AnimationAction.prototype, {
 
 					time = deltaTime > 0 ? duration : 0;
 
+					this.time = time;
+
 					this._mixer.dispatchEvent( {
 						type: 'finished', action: this,
 						direction: deltaTime > 0 ? 1 : - 1
@@ -583,26 +593,30 @@ Object.assign( AnimationAction.prototype, {
 
 					this._loopCount = loopCount;
 
+					this.time = time;
+
 					this._mixer.dispatchEvent( {
 						type: 'loop', action: this, loopDelta: loopDelta
 					} );
 
 				}
 
+			} else {
+
+				this.time = time;
+
 			}
 
 			if ( pingPong && ( loopCount & 1 ) === 1 ) {
 
 				// invert time for the "pong round"
 
-				this.time = time;
 				return duration - time;
 
 			}
 
 		}
 
-		this.time = 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 );
 
+	},
+
+	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 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;
 
@@ -1089,12 +1084,7 @@ BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototy
 
 				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;
 

+ 12 - 0
src/core/InstancedBufferAttribute.js

@@ -36,6 +36,18 @@ InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribu
 
 		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;
   bevelThickness?: number;
   bevelSize?: number;
+  bevelOffset?: number;
   bevelSegments?: number;
   extrudePath?: CurvePath<Vector3>;
   UVGenerator?: UVGenerator;

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

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

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

@@ -44,6 +44,7 @@ export interface MaterialParameters {
   dithering?: boolean;
   flatShading?: boolean;
   side?: Side;
+	shadowSide?: Side;
   transparent?: boolean;
   vertexColors?: Colors;
   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
 		 * @type {boolean}
 		 */
-		checkShaderErrors: false
+		checkShaderErrors: true
 	};
 
 	// 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;
 
+				if ( triggers[ i ] === undefined ) triggers[ i ] = false;
+
 				if ( triggers[ i ] !== gamepad.buttons[ buttonId ].pressed ) {
 
 					triggers[ i ] = gamepad.buttons[ buttonId ].pressed;

Некоторые файлы не были показаны из-за большого количества измененных файлов