2
0
Mr.doob 2 жил өмнө
parent
commit
0783e2b43a

+ 1 - 1
examples/js/animation/CCDIKSolver.js

@@ -185,7 +185,7 @@
    */
    */
 		createHelper() {
 		createHelper() {
 
 
-			return new CCDIKHelper( this.mesh, this.mesh.geometry.userData.MMD.iks );
+			return new CCDIKHelper( this.mesh, this.iks );
 
 
 		}
 		}
 
 

+ 40 - 4
examples/js/controls/OrbitControls.js

@@ -549,19 +549,55 @@
 				switch ( event.code ) {
 				switch ( event.code ) {
 
 
 					case scope.keys.UP:
 					case scope.keys.UP:
-						pan( 0, scope.keyPanSpeed );
+						if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
+
+							rotateUp( 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );
+
+						} else {
+
+							pan( 0, scope.keyPanSpeed );
+
+						}
+
 						needsUpdate = true;
 						needsUpdate = true;
 						break;
 						break;
 					case scope.keys.BOTTOM:
 					case scope.keys.BOTTOM:
-						pan( 0, - scope.keyPanSpeed );
+						if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
+
+							rotateUp( - 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );
+
+						} else {
+
+							pan( 0, - scope.keyPanSpeed );
+
+						}
+
 						needsUpdate = true;
 						needsUpdate = true;
 						break;
 						break;
 					case scope.keys.LEFT:
 					case scope.keys.LEFT:
-						pan( scope.keyPanSpeed, 0 );
+						if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
+
+							rotateLeft( 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );
+
+						} else {
+
+							pan( scope.keyPanSpeed, 0 );
+
+						}
+
 						needsUpdate = true;
 						needsUpdate = true;
 						break;
 						break;
 					case scope.keys.RIGHT:
 					case scope.keys.RIGHT:
-						pan( - scope.keyPanSpeed, 0 );
+						if ( event.ctrlKey || event.metaKey || event.shiftKey ) {
+
+							rotateLeft( - 2 * Math.PI * scope.rotateSpeed / scope.domElement.clientHeight );
+
+						} else {
+
+							pan( - scope.keyPanSpeed, 0 );
+
+						}
+
 						needsUpdate = true;
 						needsUpdate = true;
 						break;
 						break;
 
 

+ 0 - 58
examples/js/exporters/GLTFExporter.js

@@ -14,11 +14,6 @@
 
 
 				return new GLTFMaterialsUnlitExtension( writer );
 				return new GLTFMaterialsUnlitExtension( writer );
 
 
-			} );
-			this.register( function ( writer ) {
-
-				return new GLTFMaterialsPBRSpecularGlossiness( writer );
-
 			} );
 			} );
 			this.register( function ( writer ) {
 			this.register( function ( writer ) {
 
 
@@ -2011,59 +2006,6 @@
 
 
 	}
 	}
 
 
-	/**
- * Specular-Glossiness Extension
- *
- * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness
- */
-	class GLTFMaterialsPBRSpecularGlossiness {
-
-		constructor( writer ) {
-
-			this.writer = writer;
-			this.name = 'KHR_materials_pbrSpecularGlossiness';
-
-		}
-		writeMaterial( material, materialDef ) {
-
-			if ( ! material.isGLTFSpecularGlossinessMaterial ) return;
-			const writer = this.writer;
-			const extensionsUsed = writer.extensionsUsed;
-			const extensionDef = {};
-			if ( materialDef.pbrMetallicRoughness.baseColorFactor ) {
-
-				extensionDef.diffuseFactor = materialDef.pbrMetallicRoughness.baseColorFactor;
-
-			}
-
-			const specularFactor = [ 1, 1, 1 ];
-			material.specular.toArray( specularFactor, 0 );
-			extensionDef.specularFactor = specularFactor;
-			extensionDef.glossinessFactor = material.glossiness;
-			if ( materialDef.pbrMetallicRoughness.baseColorTexture ) {
-
-				extensionDef.diffuseTexture = materialDef.pbrMetallicRoughness.baseColorTexture;
-
-			}
-
-			if ( material.specularMap ) {
-
-				const specularMapDef = {
-					index: writer.processTexture( material.specularMap )
-				};
-				writer.applyTextureTransform( specularMapDef, material.specularMap );
-				extensionDef.specularGlossinessTexture = specularMapDef;
-
-			}
-
-			materialDef.extensions = materialDef.extensions || {};
-			materialDef.extensions[ this.name ] = extensionDef;
-			extensionsUsed[ this.name ] = true;
-
-		}
-
-	}
-
 	/**
 	/**
  * Clearcoat Materials Extension
  * Clearcoat Materials Extension
  *
  *

+ 9 - 9
examples/js/exporters/USDZExporter.js

@@ -8,7 +8,7 @@
 					type: 'plane'
 					type: 'plane'
 				},
 				},
 				planeAnchoring: {
 				planeAnchoring: {
-					alignment: 'vertical'
+					alignment: 'horizontal'
 				}
 				}
 			}
 			}
 		} ) {
 		} ) {
@@ -574,9 +574,9 @@ ${samplers.join( '\n' )}
 			matrix4d xformOp:transform = ${transform}
 			matrix4d xformOp:transform = ${transform}
 			uniform token[] xformOpOrder = ["xformOp:transform"]
 			uniform token[] xformOpOrder = ["xformOp:transform"]
 	
 	
-			float2 clippingRange = (${camera.near}, ${camera.far})
-			float horizontalAperture = ${( Math.abs( camera.left ) + Math.abs( camera.right ) ) * 10}
-			float verticalAperture = ${( Math.abs( camera.top ) + Math.abs( camera.bottom ) ) * 10}
+			float2 clippingRange = (${camera.near.toPrecision( PRECISION )}, ${camera.far.toPrecision( PRECISION )})
+			float horizontalAperture = ${( ( Math.abs( camera.left ) + Math.abs( camera.right ) ) * 10 ).toPrecision( PRECISION )}
+			float verticalAperture = ${( ( Math.abs( camera.top ) + Math.abs( camera.bottom ) ) * 10 ).toPrecision( PRECISION )}
 			token projection = "orthographic"
 			token projection = "orthographic"
 		}
 		}
 	
 	
@@ -589,12 +589,12 @@ ${samplers.join( '\n' )}
 			matrix4d xformOp:transform = ${transform}
 			matrix4d xformOp:transform = ${transform}
 			uniform token[] xformOpOrder = ["xformOp:transform"]
 			uniform token[] xformOpOrder = ["xformOp:transform"]
 	
 	
-			float2 clippingRange = (${camera.near}, ${camera.far})
-			float focalLength = ${camera.getFocalLength()}
-			float focusDistance = ${camera.focus}
-			float horizontalAperture = ${camera.getFilmWidth()}
+			float2 clippingRange = (${camera.near.toPrecision( PRECISION )}, ${camera.far.toPrecision( PRECISION )})
+			float focalLength = ${camera.getFocalLength().toPrecision( PRECISION )}
+			float focusDistance = ${camera.focus.toPrecision( PRECISION )}
+			float horizontalAperture = ${camera.getFilmWidth().toPrecision( PRECISION )}
 			token projection = "perspective"
 			token projection = "perspective"
-			float verticalAperture = ${camera.getFilmHeight()}
+			float verticalAperture = ${camera.getFilmHeight().toPrecision( PRECISION )}
 		}
 		}
 	
 	
 	`;
 	`;

+ 2 - 0
examples/js/lines/LineSegments2.js

@@ -33,10 +33,12 @@
 
 
 	function raycastWorldUnits( lineSegments, intersects ) {
 	function raycastWorldUnits( lineSegments, intersects ) {
 
 
+		const matrixWorld = lineSegments.matrixWorld;
 		for ( let i = 0, l = _instanceStart.count; i < l; i ++ ) {
 		for ( let i = 0, l = _instanceStart.count; i < l; i ++ ) {
 
 
 			_line.start.fromBufferAttribute( _instanceStart, i );
 			_line.start.fromBufferAttribute( _instanceStart, i );
 			_line.end.fromBufferAttribute( _instanceEnd, i );
 			_line.end.fromBufferAttribute( _instanceEnd, i );
+			_line.applyMatrix4( matrixWorld );
 			const pointOnLine = new THREE.Vector3();
 			const pointOnLine = new THREE.Vector3();
 			const point = new THREE.Vector3();
 			const point = new THREE.Vector3();
 			_ray.distanceSqToSegment( _line.start, _line.end, point, pointOnLine );
 			_ray.distanceSqToSegment( _line.start, _line.end, point, pointOnLine );

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

@@ -3358,6 +3358,33 @@
 
 
 					}
 					}
 
 
+					// Collada allows to use phong and lambert materials with lines. Replacing these cases with THREE.LineBasicMaterial.
+
+					if ( type === 'lines' || type === 'linestrips' ) {
+
+						for ( let i = 0, l = materials.length; i < l; i ++ ) {
+
+							const material = materials[ i ];
+							if ( material.isMeshPhongMaterial === true || material.isMeshLambertMaterial === true ) {
+
+								const lineMaterial = new THREE.LineBasicMaterial();
+
+								// copy compatible properties
+
+								lineMaterial.color.copy( material.color );
+								lineMaterial.opacity = material.opacity;
+								lineMaterial.transparent = material.transparent;
+
+								// replace material
+
+								materials[ i ] = lineMaterial;
+
+							}
+
+						}
+
+					}
+
 					// regard skinning
 					// regard skinning
 
 
 					const skinning = geometry.data.attributes.skinIndex !== undefined;
 					const skinning = geometry.data.attributes.skinIndex !== undefined;

+ 1 - 0
examples/js/loaders/FBXLoader.js

@@ -1706,6 +1706,7 @@
 				faceLength ++;
 				faceLength ++;
 				if ( endOfFace ) {
 				if ( endOfFace ) {
 
 
+					if ( faceLength > 4 ) console.warn( 'THREE.FBXLoader: Polygons with more than four sides are not supported. Make sure to triangulate the geometry during export.' );
 					scope.genFace( buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength );
 					scope.genFace( buffers, geoInfo, facePositionIndexes, materialIndex, faceNormals, faceColors, faceUVs, faceWeights, faceWeightIndices, faceLength );
 					polygonIndex ++;
 					polygonIndex ++;
 					faceLength = 0;
 					faceLength = 0;

+ 62 - 308
examples/js/loaders/GLTFLoader.js

@@ -264,9 +264,6 @@
 						case EXTENSIONS.KHR_MATERIALS_UNLIT:
 						case EXTENSIONS.KHR_MATERIALS_UNLIT:
 							extensions[ extensionName ] = new GLTFMaterialsUnlitExtension();
 							extensions[ extensionName ] = new GLTFMaterialsUnlitExtension();
 							break;
 							break;
-						case EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS:
-							extensions[ extensionName ] = new GLTFMaterialsPbrSpecularGlossinessExtension();
-							break;
 						case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:
 						case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:
 							extensions[ extensionName ] = new GLTFDracoMeshCompressionExtension( json, this.dracoLoader );
 							extensions[ extensionName ] = new GLTFDracoMeshCompressionExtension( json, this.dracoLoader );
 							break;
 							break;
@@ -347,7 +344,6 @@
 		KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
 		KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
 		KHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat',
 		KHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat',
 		KHR_MATERIALS_IOR: 'KHR_materials_ior',
 		KHR_MATERIALS_IOR: 'KHR_materials_ior',
-		KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
 		KHR_MATERIALS_SHEEN: 'KHR_materials_sheen',
 		KHR_MATERIALS_SHEEN: 'KHR_materials_sheen',
 		KHR_MATERIALS_SPECULAR: 'KHR_materials_specular',
 		KHR_MATERIALS_SPECULAR: 'KHR_materials_specular',
 		KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission',
 		KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission',
@@ -1513,237 +1509,6 @@
 
 
 	}
 	}
 
 
-	/**
- * Specular-Glossiness Extension
- *
- * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness
- */
-
-	/**
- * A sub class of StandardMaterial with some of the functionality
- * changed via the `onBeforeCompile` callback
- * @pailhead
- */
-	class GLTFMeshStandardSGMaterial extends THREE.MeshStandardMaterial {
-
-		constructor( params ) {
-
-			super();
-			this.isGLTFSpecularGlossinessMaterial = true;
-
-			//various chunks that need replacing
-			const specularMapParsFragmentChunk = [ '#ifdef USE_SPECULARMAP', '	uniform sampler2D specularMap;', '#endif' ].join( '\n' );
-			const glossinessMapParsFragmentChunk = [ '#ifdef USE_GLOSSINESSMAP', '	uniform sampler2D glossinessMap;', '#endif' ].join( '\n' );
-			const specularMapFragmentChunk = [ 'vec3 specularFactor = specular;', '#ifdef USE_SPECULARMAP', '	vec4 texelSpecular = texture2D( specularMap, vUv );', '	// reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture', '	specularFactor *= texelSpecular.rgb;', '#endif' ].join( '\n' );
-			const glossinessMapFragmentChunk = [ 'float glossinessFactor = glossiness;', '#ifdef USE_GLOSSINESSMAP', '	vec4 texelGlossiness = texture2D( glossinessMap, vUv );', '	// reads channel A, compatible with a glTF Specular-Glossiness (RGBA) texture', '	glossinessFactor *= texelGlossiness.a;', '#endif' ].join( '\n' );
-			const lightPhysicalFragmentChunk = [ 'PhysicalMaterial material;', 'material.diffuseColor = diffuseColor.rgb * ( 1. - max( specularFactor.r, max( specularFactor.g, specularFactor.b ) ) );', 'vec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );', 'float geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );', 'material.roughness = max( 1.0 - glossinessFactor, 0.0525 ); // 0.0525 corresponds to the base mip of a 256 cubemap.', 'material.roughness += geometryRoughness;', 'material.roughness = min( material.roughness, 1.0 );', 'material.specularColor = specularFactor;' ].join( '\n' );
-			const uniforms = {
-				specular: {
-					value: new THREE.Color().setHex( 0xffffff )
-				},
-				glossiness: {
-					value: 1
-				},
-				specularMap: {
-					value: null
-				},
-				glossinessMap: {
-					value: null
-				}
-			};
-			this._extraUniforms = uniforms;
-			this.onBeforeCompile = function ( shader ) {
-
-				for ( const uniformName in uniforms ) {
-
-					shader.uniforms[ uniformName ] = uniforms[ uniformName ];
-
-				}
-
-				shader.fragmentShader = shader.fragmentShader.replace( 'uniform float roughness;', 'uniform vec3 specular;' ).replace( 'uniform float metalness;', 'uniform float glossiness;' ).replace( '#include <roughnessmap_pars_fragment>', specularMapParsFragmentChunk ).replace( '#include <metalnessmap_pars_fragment>', glossinessMapParsFragmentChunk ).replace( '#include <roughnessmap_fragment>', specularMapFragmentChunk ).replace( '#include <metalnessmap_fragment>', glossinessMapFragmentChunk ).replace( '#include <lights_physical_fragment>', lightPhysicalFragmentChunk );
-
-			};
-
-			Object.defineProperties( this, {
-				specular: {
-					get: function () {
-
-						return uniforms.specular.value;
-
-					},
-					set: function ( v ) {
-
-						uniforms.specular.value = v;
-
-					}
-				},
-				specularMap: {
-					get: function () {
-
-						return uniforms.specularMap.value;
-
-					},
-					set: function ( v ) {
-
-						uniforms.specularMap.value = v;
-						if ( v ) {
-
-							this.defines.USE_SPECULARMAP = ''; // USE_UV is set by the renderer for specular maps
-
-						} else {
-
-							delete this.defines.USE_SPECULARMAP;
-
-						}
-
-					}
-				},
-				glossiness: {
-					get: function () {
-
-						return uniforms.glossiness.value;
-
-					},
-					set: function ( v ) {
-
-						uniforms.glossiness.value = v;
-
-					}
-				},
-				glossinessMap: {
-					get: function () {
-
-						return uniforms.glossinessMap.value;
-
-					},
-					set: function ( v ) {
-
-						uniforms.glossinessMap.value = v;
-						if ( v ) {
-
-							this.defines.USE_GLOSSINESSMAP = '';
-							this.defines.USE_UV = '';
-
-						} else {
-
-							delete this.defines.USE_GLOSSINESSMAP;
-							delete this.defines.USE_UV;
-
-						}
-
-					}
-				}
-			} );
-			delete this.metalness;
-			delete this.roughness;
-			delete this.metalnessMap;
-			delete this.roughnessMap;
-			this.setValues( params );
-
-		}
-		copy( source ) {
-
-			super.copy( source );
-			this.specularMap = source.specularMap;
-			this.specular.copy( source.specular );
-			this.glossinessMap = source.glossinessMap;
-			this.glossiness = source.glossiness;
-			delete this.metalness;
-			delete this.roughness;
-			delete this.metalnessMap;
-			delete this.roughnessMap;
-			return this;
-
-		}
-
-	}
-	class GLTFMaterialsPbrSpecularGlossinessExtension {
-
-		constructor() {
-
-			this.name = EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS;
-			this.specularGlossinessParams = [ 'color', 'map', 'lightMap', 'lightMapIntensity', 'aoMap', 'aoMapIntensity', 'emissive', 'emissiveIntensity', 'emissiveMap', 'bumpMap', 'bumpScale', 'normalMap', 'normalMapType', 'displacementMap', 'displacementScale', 'displacementBias', 'specularMap', 'specular', 'glossinessMap', 'glossiness', 'alphaMap', 'envMap', 'envMapIntensity' ];
-
-		}
-		getMaterialType() {
-
-			return GLTFMeshStandardSGMaterial;
-
-		}
-		extendParams( materialParams, materialDef, parser ) {
-
-			const pbrSpecularGlossiness = materialDef.extensions[ this.name ];
-			materialParams.color = new THREE.Color( 1.0, 1.0, 1.0 );
-			materialParams.opacity = 1.0;
-			const pending = [];
-			if ( Array.isArray( pbrSpecularGlossiness.diffuseFactor ) ) {
-
-				const array = pbrSpecularGlossiness.diffuseFactor;
-				materialParams.color.fromArray( array );
-				materialParams.opacity = array[ 3 ];
-
-			}
-
-			if ( pbrSpecularGlossiness.diffuseTexture !== undefined ) {
-
-				pending.push( parser.assignTexture( materialParams, 'map', pbrSpecularGlossiness.diffuseTexture, THREE.sRGBEncoding ) );
-
-			}
-
-			materialParams.emissive = new THREE.Color( 0.0, 0.0, 0.0 );
-			materialParams.glossiness = pbrSpecularGlossiness.glossinessFactor !== undefined ? pbrSpecularGlossiness.glossinessFactor : 1.0;
-			materialParams.specular = new THREE.Color( 1.0, 1.0, 1.0 );
-			if ( Array.isArray( pbrSpecularGlossiness.specularFactor ) ) {
-
-				materialParams.specular.fromArray( pbrSpecularGlossiness.specularFactor );
-
-			}
-
-			if ( pbrSpecularGlossiness.specularGlossinessTexture !== undefined ) {
-
-				const specGlossMapDef = pbrSpecularGlossiness.specularGlossinessTexture;
-				pending.push( parser.assignTexture( materialParams, 'glossinessMap', specGlossMapDef ) );
-				pending.push( parser.assignTexture( materialParams, 'specularMap', specGlossMapDef, THREE.sRGBEncoding ) );
-
-			}
-
-			return Promise.all( pending );
-
-		}
-		createMaterial( materialParams ) {
-
-			const material = new GLTFMeshStandardSGMaterial( materialParams );
-			material.fog = true;
-			material.color = materialParams.color;
-			material.map = materialParams.map === undefined ? null : materialParams.map;
-			material.lightMap = null;
-			material.lightMapIntensity = 1.0;
-			material.aoMap = materialParams.aoMap === undefined ? null : materialParams.aoMap;
-			material.aoMapIntensity = 1.0;
-			material.emissive = materialParams.emissive;
-			material.emissiveIntensity = materialParams.emissiveIntensity === undefined ? 1.0 : materialParams.emissiveIntensity;
-			material.emissiveMap = materialParams.emissiveMap === undefined ? null : materialParams.emissiveMap;
-			material.bumpMap = materialParams.bumpMap === undefined ? null : materialParams.bumpMap;
-			material.bumpScale = 1;
-			material.normalMap = materialParams.normalMap === undefined ? null : materialParams.normalMap;
-			material.normalMapType = THREE.TangentSpaceNormalMap;
-			if ( materialParams.normalScale ) material.normalScale = materialParams.normalScale;
-			material.displacementMap = null;
-			material.displacementScale = 1;
-			material.displacementBias = 0;
-			material.specularMap = materialParams.specularMap === undefined ? null : materialParams.specularMap;
-			material.specular = materialParams.specular;
-			material.glossinessMap = materialParams.glossinessMap === undefined ? null : materialParams.glossinessMap;
-			material.glossiness = materialParams.glossiness;
-			material.alphaMap = null;
-			material.envMap = materialParams.envMap === undefined ? null : materialParams.envMap;
-			material.envMapIntensity = 1.0;
-			return material;
-
-		}
-
-	}
-
 	/**
 	/**
  * THREE.Mesh Quantization Extension
  * THREE.Mesh Quantization Extension
  *
  *
@@ -2199,9 +1964,17 @@
 			// Use an THREE.ImageBitmapLoader if imageBitmaps are supported. Moves much of the
 			// Use an THREE.ImageBitmapLoader if imageBitmaps are supported. Moves much of the
 			// expensive work of uploading a texture to the GPU off the main thread.
 			// expensive work of uploading a texture to the GPU off the main thread.
 
 
-			const isSafari = /^((?!chrome|android).)*safari/i.test( navigator.userAgent ) === true;
-			const isFirefox = navigator.userAgent.indexOf( 'Firefox' ) > - 1;
-			const firefoxVersion = isFirefox ? navigator.userAgent.match( /Firefox\/([0-9]+)\./ )[ 1 ] : - 1;
+			let isSafari = false;
+			let isFirefox = false;
+			let firefoxVersion = - 1;
+			if ( typeof navigator !== 'undefined' ) {
+
+				isSafari = /^((?!chrome|android).)*safari/i.test( navigator.userAgent ) === true;
+				isFirefox = navigator.userAgent.indexOf( 'Firefox' ) > - 1;
+				firefoxVersion = isFirefox ? navigator.userAgent.match( /Firefox\/([0-9]+)\./ )[ 1 ] : - 1;
+
+			}
+
 			if ( typeof createImageBitmap === 'undefined' || isSafari || isFirefox && firefoxVersion < 98 ) {
 			if ( typeof createImageBitmap === 'undefined' || isSafari || isFirefox && firefoxVersion < 98 ) {
 
 
 				this.textureLoader = new THREE.TextureLoader( this.options.manager );
 				this.textureLoader = new THREE.TextureLoader( this.options.manager );
@@ -2712,7 +2485,7 @@
 		/**
 		/**
    * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#textures
    * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#textures
    * @param {number} textureIndex
    * @param {number} textureIndex
-   * @return {Promise<THREE.Texture>}
+   * @return {Promise<THREE.Texture|null>}
    */
    */
 		loadTexture( textureIndex ) {
 		loadTexture( textureIndex ) {
 
 
@@ -2863,6 +2636,8 @@
 			const parser = this;
 			const parser = this;
 			return this.getDependency( 'texture', mapDef.index ).then( function ( texture ) {
 			return this.getDependency( 'texture', mapDef.index ).then( function ( texture ) {
 
 
+				if ( ! texture ) return null;
+
 				// Materials sample aoMap from UV set 1 and other maps from UV set 0 - this can't be configured
 				// Materials sample aoMap from UV set 1 and other maps from UV set 0 - this can't be configured
 				// However, we will copy UV set 0 to UV set 1 on demand for aoMap
 				// However, we will copy UV set 0 to UV set 1 on demand for aoMap
 				if ( mapDef.texCoord !== undefined && mapDef.texCoord != 0 && ! ( mapName === 'aoMap' && mapDef.texCoord == 1 ) ) {
 				if ( mapDef.texCoord !== undefined && mapDef.texCoord != 0 && ! ( mapName === 'aoMap' && mapDef.texCoord == 1 ) ) {
@@ -2951,7 +2726,6 @@
 			if ( useDerivativeTangents || useVertexColors || useFlatShading ) {
 			if ( useDerivativeTangents || useVertexColors || useFlatShading ) {
 
 
 				let cacheKey = 'ClonedMaterial:' + material.uuid + ':';
 				let cacheKey = 'ClonedMaterial:' + material.uuid + ':';
-				if ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:';
 				if ( useDerivativeTangents ) cacheKey += 'derivative-tangents:';
 				if ( useDerivativeTangents ) cacheKey += 'derivative-tangents:';
 				if ( useVertexColors ) cacheKey += 'vertex-colors:';
 				if ( useVertexColors ) cacheKey += 'vertex-colors:';
 				if ( useFlatShading ) cacheKey += 'flat-shading:';
 				if ( useFlatShading ) cacheKey += 'flat-shading:';
@@ -3010,13 +2784,7 @@
 			const materialParams = {};
 			const materialParams = {};
 			const materialExtensions = materialDef.extensions || {};
 			const materialExtensions = materialDef.extensions || {};
 			const pending = [];
 			const pending = [];
-			if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ] ) {
-
-				const sgExtension = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ];
-				materialType = sgExtension.getMaterialType();
-				pending.push( sgExtension.extendParams( materialParams, materialDef, parser ) );
-
-			} else if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] ) {
+			if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] ) {
 
 
 				const kmuExtension = extensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ];
 				const kmuExtension = extensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ];
 				materialType = kmuExtension.getMaterialType();
 				materialType = kmuExtension.getMaterialType();
@@ -3129,17 +2897,7 @@
 
 
 			return Promise.all( pending ).then( function () {
 			return Promise.all( pending ).then( function () {
 
 
-				let material;
-				if ( materialType === GLTFMeshStandardSGMaterial ) {
-
-					material = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].createMaterial( materialParams );
-
-				} else {
-
-					material = new materialType( materialParams );
-
-				}
-
+				const material = new materialType( materialParams );
 				if ( materialDef.name ) material.name = materialDef.name;
 				if ( materialDef.name ) material.name = materialDef.name;
 				assignExtrasToUserData( material, materialDef );
 				assignExtrasToUserData( material, materialDef );
 				parser.associations.set( material, {
 				parser.associations.set( material, {
@@ -3394,24 +3152,58 @@
 		/**
 		/**
    * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins
    * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins
    * @param {number} skinIndex
    * @param {number} skinIndex
-   * @return {Promise<Object>}
+   * @return {Promise<Skeleton>}
    */
    */
 		loadSkin( skinIndex ) {
 		loadSkin( skinIndex ) {
 
 
 			const skinDef = this.json.skins[ skinIndex ];
 			const skinDef = this.json.skins[ skinIndex ];
-			const skinEntry = {
-				joints: skinDef.joints
-			};
-			if ( skinDef.inverseBindMatrices === undefined ) {
+			const pending = [];
+			for ( let i = 0, il = skinDef.joints.length; i < il; i ++ ) {
 
 
-				return Promise.resolve( skinEntry );
+				pending.push( this.getDependency( 'node', skinDef.joints[ i ] ) );
 
 
 			}
 			}
 
 
-			return this.getDependency( 'accessor', skinDef.inverseBindMatrices ).then( function ( accessor ) {
+			if ( skinDef.inverseBindMatrices !== undefined ) {
 
 
-				skinEntry.inverseBindMatrices = accessor;
-				return skinEntry;
+				pending.push( this.getDependency( 'accessor', skinDef.inverseBindMatrices ) );
+
+			} else {
+
+				pending.push( null );
+
+			}
+
+			return Promise.all( pending ).then( function ( results ) {
+
+				const inverseBindMatrices = results.pop();
+				const jointNodes = results;
+				const bones = [];
+				const boneInverses = [];
+				for ( let i = 0, il = jointNodes.length; i < il; i ++ ) {
+
+					const jointNode = jointNodes[ i ];
+					if ( jointNode ) {
+
+						bones.push( jointNode );
+						const mat = new THREE.Matrix4();
+						if ( inverseBindMatrices !== null ) {
+
+							mat.fromArray( inverseBindMatrices.array, i * 16 );
+
+						}
+
+						boneInverses.push( mat );
+
+					} else {
+
+						console.warn( 'THREE.GLTFLoader: Joint "%s" could not be found.', skinDef.joints[ i ] );
+
+					}
+
+				}
+
+				return new THREE.Skeleton( bones, boneInverses );
 
 
 			} );
 			} );
 
 
@@ -3790,50 +3582,12 @@
 
 
 			// build skeleton here as well
 			// build skeleton here as well
 
 
-			let skinEntry;
-			return parser.getDependency( 'skin', nodeDef.skin ).then( function ( skin ) {
-
-				skinEntry = skin;
-				const pendingJoints = [];
-				for ( let i = 0, il = skinEntry.joints.length; i < il; i ++ ) {
-
-					pendingJoints.push( parser.getDependency( 'node', skinEntry.joints[ i ] ) );
-
-				}
-
-				return Promise.all( pendingJoints );
-
-			} ).then( function ( jointNodes ) {
+			return parser.getDependency( 'skin', nodeDef.skin ).then( function ( skeleton ) {
 
 
 				node.traverse( function ( mesh ) {
 				node.traverse( function ( mesh ) {
 
 
-					if ( ! mesh.isMesh ) return;
-					const bones = [];
-					const boneInverses = [];
-					for ( let j = 0, jl = jointNodes.length; j < jl; j ++ ) {
-
-						const jointNode = jointNodes[ j ];
-						if ( jointNode ) {
-
-							bones.push( jointNode );
-							const mat = new THREE.Matrix4();
-							if ( skinEntry.inverseBindMatrices !== undefined ) {
-
-								mat.fromArray( skinEntry.inverseBindMatrices.array, j * 16 );
-
-							}
-
-							boneInverses.push( mat );
-
-						} else {
-
-							console.warn( 'THREE.GLTFLoader: Joint "%s" could not be found.', skinEntry.joints[ j ] );
-
-						}
-
-					}
-
-					mesh.bind( new THREE.Skeleton( bones, boneInverses ), mesh.matrixWorld );
+					if ( ! mesh.isSkinnedMesh ) return;
+					mesh.bind( skeleton, mesh.matrixWorld );
 
 
 				} );
 				} );
 				return node;
 				return node;

+ 0 - 392
examples/js/loaders/MaterialXLoader.js

@@ -1,392 +0,0 @@
-( function () {
-const colorSpaceLib = {
-  THREE.mx_srgb_texture_to_lin_rec709
-};
-class MtlXElement {
-  constructor(name, nodeFunc, params = null) {
-    this.name = name;
-    this.nodeFunc = nodeFunc;
-    this.params = params;
-  }
-}
-
-// Ref: https://github.com/mrdoob/three.js/issues/24674
-
-const MtlXElements = [
-// << Math >>
-new MtlXElement('add', THREE.add, ['in1', 'in2']), new MtlXElement('subtract', THREE.sub, ['in1', 'in2']), new MtlXElement('multiply', THREE.mul, ['in1', 'in2']), new MtlXElement('divide', THREE.div, ['in1', 'in2']), new MtlXElement('modulo', THREE.mod, ['in1', 'in2']), new MtlXElement('absval', THREE.abs, ['in1', 'in2']), new MtlXElement('sign', THREE.sign, ['in1', 'in2']), new MtlXElement('floor', THREE.floor, ['in1', 'in2']), new MtlXElement('ceil', THREE.ceil, ['in1', 'in2']), new MtlXElement('round', THREE.round, ['in1', 'in2']), new MtlXElement('power', THREE.pow, ['in1', 'in2']), new MtlXElement('sin', THREE.sin, ['in']), new MtlXElement('cos', THREE.cos, ['in']), new MtlXElement('tan', THREE.tan, ['in']), new MtlXElement('asin', THREE.asin, ['in']), new MtlXElement('acos', THREE.acos, ['in']), new MtlXElement('atan2', THREE.atan2, ['in1', 'in2']), new MtlXElement('sqrt', THREE.sqrt, ['in']),
-//new MtlXElement( 'ln', ... ),
-new MtlXElement('exp', THREE.exp, ['in']), new MtlXElement('clamp', THREE.clamp, ['in', 'low', 'high']), new MtlXElement('min', THREE.min, ['in1', 'in2']), new MtlXElement('max', THREE.max, ['in1', 'in2']), new MtlXElement('normalize', THREE.normalize, ['in']), new MtlXElement('magnitude', THREE.length, ['in1', 'in2']), new MtlXElement('dotproduct', THREE.dot, ['in1', 'in2']), new MtlXElement('crossproduct', THREE.cross, ['in']),
-//new MtlXElement( 'transformpoint', ... ),
-//new MtlXElement( 'transformvector', ... ),
-//new MtlXElement( 'transformnormal', ... ),
-//new MtlXElement( 'transformmatrix', ... ),
-new MtlXElement('normalmap', THREE.normalMap, ['in', 'scale']),
-//new MtlXElement( 'transpose', ... ),
-//new MtlXElement( 'determinant', ... ),
-//new MtlXElement( 'invertmatrix', ... ),
-//new MtlXElement( 'rotate2d', rotateUV, [ 'in', radians( 'amount' )** ] ),
-//new MtlXElement( 'rotate3d', ... ),
-//new MtlXElement( 'arrayappend', ... ),
-//new MtlXElement( 'dot', ... ),
-
-// << Adjustment >>
-new MtlXElement('remap', THREE.remap, ['in', 'inlow', 'inhigh', 'outlow', 'outhigh']), new MtlXElement('smoothstep', THREE.smoothstep, ['in', 'low', 'high']),
-//new MtlXElement( 'curveadjust', ... ),
-//new MtlXElement( 'curvelookup', ... ),
-new MtlXElement('luminance', THREE.luminance, ['in', 'lumacoeffs']), new MtlXElement('rgbtohsv', THREE.mx_rgbtohsv, ['in']), new MtlXElement('hsvtorgb', THREE.mx_hsvtorgb, ['in']),
-// << Mix >>
-new MtlXElement('mix', THREE.mix, ['bg', 'fg', 'mix']),
-// << Channel >>
-new MtlXElement('combine2', THREE.vec2, ['in1', 'in2']), new MtlXElement('combine3', THREE.vec3, ['in1', 'in2', 'in3']), new MtlXElement('combine4', THREE.vec4, ['in1', 'in2', 'in3', 'in4']),
-// << Procedural >>
-new MtlXElement('ramplr', THREE.mx_ramplr, ['valuel', 'valuer', 'texcoord']), new MtlXElement('ramptb', THREE.mx_ramptb, ['valuet', 'valueb', 'texcoord']), new MtlXElement('splitlr', THREE.mx_splitlr, ['valuel', 'valuer', 'texcoord']), new MtlXElement('splittb', THREE.mx_splittb, ['valuet', 'valueb', 'texcoord']), new MtlXElement('noise2d', THREE.mx_noise_float, ['texcoord', 'amplitude', 'pivot']), new MtlXElement('noise3d', THREE.mx_noise_float, ['texcoord', 'amplitude', 'pivot']), new MtlXElement('fractal3d', THREE.mx_fractal_noise_float, ['position', 'octaves', 'lacunarity', 'diminish', 'amplitude']), new MtlXElement('cellnoise2d', THREE.mx_cell_noise_float, ['texcoord']), new MtlXElement('cellnoise3d', THREE.mx_cell_noise_float, ['texcoord']), new MtlXElement('worleynoise2d', THREE.mx_worley_noise_float, ['texcoord', 'jitter']), new MtlXElement('worleynoise3d', THREE.mx_worley_noise_float, ['texcoord', 'jitter']),
-// << Supplemental >>
-//new MtlXElement( 'tiledimage', ... ),
-//new MtlXElement( 'triplanarprojection', triplanarTextures, [ 'filex', 'filey', 'filez' ] ),
-//new MtlXElement( 'ramp4', ... ),
-//new MtlXElement( 'place2d', mx_place2d, [ 'texcoord', 'pivot', 'scale', 'rotate', 'offset' ] ),
-new MtlXElement('safepower', THREE.mx_safepower, ['in1', 'in2']), new MtlXElement('contrast', THREE.mx_contrast, ['in', 'amount', 'pivot']),
-//new MtlXElement( 'hsvadjust', ... ),
-new MtlXElement('saturate', THREE.saturation, ['in', 'amount'])
-//new MtlXElement( 'extract', ... ),
-//new MtlXElement( 'separate2', ... ),
-//new MtlXElement( 'separate3', ... ),
-//new MtlXElement( 'separate4', ... )
-];
-
-const MtlXLibrary = {};
-MtlXElements.forEach(element => MtlXLibrary[element.name] = element);
-class MaterialXLoader extends THREE.Loader {
-  constructor(manager) {
-    super(manager);
-  }
-  load(url, onLoad, onProgress, onError) {
-    new THREE.FileLoader(this.manager).setPath(this.path).load(url, async text => {
-      try {
-        onLoad(this.parse(text));
-      } catch (e) {
-        onError(e);
-      }
-    }, onProgress, onError);
-    return this;
-  }
-  parse(text) {
-    return new MaterialX(this.manager, this.path).parse(text);
-  }
-}
-class MaterialXNode {
-  constructor(materialX, nodeXML, nodePath = '') {
-    this.materialX = materialX;
-    this.nodeXML = nodeXML;
-    this.nodePath = nodePath ? nodePath + '/' + this.name : this.name;
-    this.parent = null;
-    this.node = null;
-    this.children = [];
-  }
-  get element() {
-    return this.nodeXML.nodeName;
-  }
-  get nodeGraph() {
-    return this.getAttribute('nodegraph');
-  }
-  get nodeName() {
-    return this.getAttribute('nodename');
-  }
-  get interfaceName() {
-    return this.getAttribute('interfacename');
-  }
-  get output() {
-    return this.getAttribute('output');
-  }
-  get name() {
-    return this.getAttribute('name');
-  }
-  get type() {
-    return this.getAttribute('type');
-  }
-  get value() {
-    return this.getAttribute('value');
-  }
-  getNodeGraph() {
-    let nodeX = this;
-    while (nodeX !== null) {
-      if (nodeX.element === 'nodegraph') {
-        break;
-      }
-      nodeX = nodeX.parent;
-    }
-    return nodeX;
-  }
-  getRoot() {
-    let nodeX = this;
-    while (nodeX.parent !== null) {
-      nodeX = nodeX.parent;
-    }
-    return nodeX;
-  }
-  get referencePath() {
-    let referencePath = null;
-    if (this.nodeGraph !== null && this.output !== null) {
-      referencePath = this.nodeGraph + '/' + this.output;
-    } else if (this.nodeName !== null || this.interfaceName !== null) {
-      referencePath = this.getNodeGraph().nodePath + '/' + (this.nodeName || this.interfaceName);
-    }
-    return referencePath;
-  }
-  get hasReference() {
-    return this.referencePath !== null;
-  }
-  get isConst() {
-    return this.element === 'input' && this.value !== null && this.type !== 'filename';
-  }
-  getColorSpaceNode() {
-    const csSource = this.getAttribute('colorspace');
-    const csTarget = this.getRoot().getAttribute('colorspace');
-    const nodeName = `mx_${csSource}_to_${csTarget}`;
-    return colorSpaceLib[nodeName];
-  }
-  getTexture() {
-    const filePrefix = this.getRecursiveAttribute('fileprefix') || '';
-    const THREE.texture = this.materialX.textureLoader.load(filePrefix + this.value);
-    THREE.texture.wrapS = THREE.texture.wrapT = THREE.RepeatWrapping;
-    THREE.texture.flipY = false;
-    return THREE.texture;
-  }
-  getClassFromType(type) {
-    let nodeClass = null;
-    if (type === 'integer') nodeClass = THREE.int;else if (type === 'float') nodeClass = THREE.float;else if (type === 'vector2') nodeClass = THREE.vec2;else if (type === 'vector3') nodeClass = THREE.vec3;else if (type === 'vector4' || type === 'color4') nodeClass = THREE.vec4;else if (type === 'color3') nodeClass = THREE.color;else if (type === 'boolean') nodeClass = THREE.bool;
-    return nodeClass;
-  }
-  getNode() {
-    let node = this.node;
-    if (node !== null) {
-      return node;
-    }
-
-    //
-
-    const type = this.type;
-    if (this.isConst) {
-      const nodeClass = this.getClassFromType(type);
-      node = nodeClass(...this.getVector());
-    } else if (this.hasReference) {
-      node = this.materialX.getMaterialXNode(this.referencePath).getNode();
-    } else {
-      const element = this.element;
-      if (element === 'convert') {
-        const nodeClass = this.getClassFromType(type);
-        node = nodeClass(this.getNodeByName('in'));
-      } else if (element === 'constant') {
-        node = this.getNodeByName('value');
-      } else if (element === 'position') {
-        node = THREE.positionLocal;
-      } else if (element === 'tiledimage') {
-        const file = this.getChildByName('file');
-        const textureFile = file.getTexture();
-        const uvTiling = THREE.mx_transform_uv(...this.getNodesByNames(['uvtiling', 'uvoffset']));
-        node = THREE.texture(textureFile, uvTiling);
-        const colorSpaceNode = file.getColorSpaceNode();
-        if (colorSpaceNode) {
-          node = colorSpaceNode(node);
-        }
-      } else if (element === 'image') {
-        const file = this.getChildByName('file');
-        const uvNode = this.getNodeByName('texcoord');
-        const textureFile = file.getTexture();
-        node = THREE.texture(textureFile, uvNode);
-        const colorSpaceNode = file.getColorSpaceNode();
-        if (colorSpaceNode) {
-          node = colorSpaceNode(node);
-        }
-      } else if (MtlXLibrary[element] !== undefined) {
-        const nodeElement = MtlXLibrary[element];
-        node = nodeElement.nodeFunc(...this.getNodesByNames(...nodeElement.params));
-      }
-    }
-
-    //
-
-    if (node === null) {
-      console.warn(`THREE.MaterialXLoader: Unexpected node ${new XMLSerializer().serializeToString(this.nodeXML)}.`);
-      node = THREE.float(0);
-    }
-
-    //
-
-    const nodeToTypeClass = this.getClassFromType(type);
-    if (nodeToTypeClass !== null) {
-      node = nodeToTypeClass(node);
-    }
-    node.name = this.name;
-    this.node = node;
-    return node;
-  }
-  getChildByName(name) {
-    for (const input of this.children) {
-      if (input.name === name) {
-        return input;
-      }
-    }
-  }
-  getNodes() {
-    const nodes = {};
-    for (const input of this.children) {
-      const node = input.getNode();
-      nodes[node.name] = node;
-    }
-    return nodes;
-  }
-  getNodeByName(name) {
-    return this.getChildByName(name)?.getNode();
-  }
-  getNodesByNames(...names) {
-    const nodes = [];
-    for (const name of names) {
-      const node = this.getNodeByName(name);
-      if (node) nodes.push(node);
-    }
-    return nodes;
-  }
-  getValue() {
-    return this.value.trim();
-  }
-  getVector() {
-    const vector = [];
-    for (const val of this.getValue().split(/[,|\s]/)) {
-      if (val !== '') {
-        vector.push(Number(val.trim()));
-      }
-    }
-    return vector;
-  }
-  getAttribute(name) {
-    return this.nodeXML.getAttribute(name);
-  }
-  getRecursiveAttribute(name) {
-    let attribute = this.nodeXML.getAttribute(name);
-    if (attribute === null && this.parent !== null) {
-      attribute = this.parent.getRecursiveAttribute(name);
-    }
-    return attribute;
-  }
-  setStandardSurfaceToGltfPBR(material) {
-    const inputs = this.getNodes();
-
-    //
-
-    let colorNode = null;
-    if (inputs.base && inputs.base_color) colorNode = THREE.mul(inputs.base, inputs.base_color);else if (inputs.base) colorNode = inputs.base;else if (inputs.base_color) colorNode = inputs.base_color;
-
-    //
-
-    let roughnessNode = null;
-    if (inputs.specular_roughness) roughnessNode = inputs.specular_roughness;
-
-    //
-
-    let metalnessNode = null;
-    if (inputs.metalness) metalnessNode = inputs.metalness;
-
-    //
-
-    let clearcoatNode = null;
-    let clearcoatRoughnessNode = null;
-    if (inputs.coat) clearcoatNode = inputs.coat;
-    if (inputs.coat_roughness) clearcoatRoughnessNode = inputs.coat_roughness;
-    if (inputs.coat_color) {
-      colorNode = colorNode ? THREE.mul(colorNode, inputs.coat_color) : colorNode;
-    }
-
-    //
-
-    material.colorNode = colorNode || THREE.color(0.8, 0.8, 0.8);
-    material.roughnessNode = roughnessNode || THREE.float(0.2);
-    material.metalnessNode = metalnessNode || THREE.float(0);
-    material.clearcoatNode = clearcoatNode || THREE.float(0);
-    material.clearcoatRoughnessNode = clearcoatRoughnessNode || THREE.float(0);
-  }
-
-  /*setGltfPBR( material ) {
-  		const inputs = this.getNodes();
-  		console.log( inputs );
-  	}*/
-
-  setMaterial(material) {
-    const element = this.element;
-    if (element === 'gltf_pbr') {
-
-      //this.setGltfPBR( material );
-    } else if (element === 'standard_surface') {
-      this.setStandardSurfaceToGltfPBR(material);
-    }
-  }
-  toMaterial() {
-    const material = new THREE.MeshPhysicalNodeMaterial();
-    material.name = this.name;
-    for (const nodeX of this.children) {
-      const shaderProperties = this.materialX.getMaterialXNode(nodeX.nodeName);
-      shaderProperties.setMaterial(material);
-    }
-    return material;
-  }
-  toMaterials() {
-    const materials = {};
-    for (const nodeX of this.children) {
-      if (nodeX.element === 'surfacematerial') {
-        const material = nodeX.toMaterial();
-        materials[material.name] = material;
-      }
-    }
-    return materials;
-  }
-  THREE.add(materialXNode) {
-    materialXNode.parent = this;
-    this.children.push(materialXNode);
-  }
-}
-class MaterialX {
-  constructor(manager, path) {
-    this.manager = manager;
-    this.path = path;
-    this.resourcePath = '';
-    this.nodesXLib = new Map();
-    //this.nodesXRefLib = new WeakMap();
-
-    this.textureLoader = new THREE.TextureLoader(manager);
-  }
-  addMaterialXNode(materialXNode) {
-    this.nodesXLib.set(materialXNode.nodePath, materialXNode);
-  }
-
-  /*getMaterialXNodeFromXML( xmlNode ) {
-       return this.nodesXRefLib.get( xmlNode );
-   }*/
-
-  getMaterialXNode(...names) {
-    return this.nodesXLib.get(names.join('/'));
-  }
-  parseNode(nodeXML, nodePath = '') {
-    const materialXNode = new MaterialXNode(this, nodeXML, nodePath);
-    if (materialXNode.nodePath) this.addMaterialXNode(materialXNode);
-    for (const childNodeXML of nodeXML.children) {
-      const childMXNode = this.parseNode(childNodeXML, materialXNode.nodePath);
-      materialXNode.add(childMXNode);
-    }
-    return materialXNode;
-  }
-  parse(text) {
-    const rootXML = new DOMParser().parseFromString(text, 'application/xml').documentElement;
-    this.textureLoader.setPath(this.path);
-
-    //
-
-    const materials = this.parseNode(rootXML).toMaterials();
-    return {
-      materials
-    };
-  }
-}
-
-THREE.MaterialXLoader = MaterialXLoader;
-} )();

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

@@ -109,7 +109,7 @@
 
 
 				// remove comments
 				// remove comments
 
 
-				PCDheader.str = PCDheader.str.replace( /\#.*/gi, '' );
+				PCDheader.str = PCDheader.str.replace( /#.*/gi, '' );
 
 
 				// parse
 				// parse
 
 

+ 55 - 11
examples/js/loaders/PLYLoader.js

@@ -24,6 +24,16 @@
  *	diffuse_blue: 'blue'
  *	diffuse_blue: 'blue'
  * } );
  * } );
  *
  *
+ * Custom properties outside of the defaults for position, uv, normal
+ * and color attributes can be added using the setCustomPropertyMapping method.
+ * For example, the following maps the element properties “custom_property_a”
+ * and “custom_property_b” to an attribute “customAttribute” with an item size of 2.
+ * Attribute item sizes are set from the number of element properties in the property array.
+ *
+ * loader.setCustomPropertyMapping( {
+ *	customAttribute: ['custom_property_a', 'custom_property_b'],
+ * } );
+ *
  */
  */
 
 
 	const _color = new THREE.Color();
 	const _color = new THREE.Color();
@@ -33,6 +43,7 @@
 
 
 			super( manager );
 			super( manager );
 			this.propertyNameMapping = {};
 			this.propertyNameMapping = {};
+			this.customPropertyMapping = {};
 
 
 		}
 		}
 		load( url, onLoad, onProgress, onError ) {
 		load( url, onLoad, onProgress, onError ) {
@@ -72,6 +83,11 @@
 
 
 			this.propertyNameMapping = mapping;
 			this.propertyNameMapping = mapping;
 
 
+		}
+		setCustomPropertyNameMapping( mapping ) {
+
+			this.customPropertyMapping = mapping;
+
 		}
 		}
 		parse( data ) {
 		parse( data ) {
 
 
@@ -232,9 +248,7 @@
 
 
 			}
 			}
 
 
-			function parseASCII( data, header ) {
-
-				// PLY ascii format specification, as per http://en.wikipedia.org/wiki/PLY_(file_format)
+			function createBuffer() {
 
 
 				const buffer = {
 				const buffer = {
 					indices: [],
 					indices: [],
@@ -244,6 +258,21 @@
 					faceVertexUvs: [],
 					faceVertexUvs: [],
 					colors: []
 					colors: []
 				};
 				};
+				for ( const customProperty of Object.keys( scope.customPropertyMapping ) ) {
+
+					buffer[ customProperty ] = [];
+
+				}
+
+				return buffer;
+
+			}
+
+			function parseASCII( data, header ) {
+
+				// PLY ascii format specification, as per http://en.wikipedia.org/wiki/PLY_(file_format)
+
+				const buffer = createBuffer();
 				let result;
 				let result;
 				const patternBody = /end_header\s([\s\S]*)$/;
 				const patternBody = /end_header\s([\s\S]*)$/;
 				let body = '';
 				let body = '';
@@ -324,6 +353,18 @@
 
 
 				}
 				}
 
 
+				// custom buffer data
+
+				for ( const customProperty of Object.keys( scope.customPropertyMapping ) ) {
+
+					if ( buffer[ customProperty ].length > 0 ) {
+
+						geometry.setAttribute( customProperty, new THREE.Float32BufferAttribute( buffer[ customProperty ], scope.customPropertyMapping[ customProperty ].length ) );
+
+					}
+
+				}
+
 				geometry.computeBoundingSphere();
 				geometry.computeBoundingSphere();
 				return geometry;
 				return geometry;
 
 
@@ -377,6 +418,16 @@
 
 
 					}
 					}
 
 
+					for ( const customProperty of Object.keys( scope.customPropertyMapping ) ) {
+
+						for ( const elementProperty of scope.customPropertyMapping[ customProperty ] ) {
+
+							buffer[ customProperty ].push( element[ elementProperty ] );
+
+						}
+
+					}
+
 				} else if ( elementName === 'face' ) {
 				} else if ( elementName === 'face' ) {
 
 
 					const vertex_indices = element.vertex_indices || element.vertex_index; // issue #9338
 					const vertex_indices = element.vertex_indices || element.vertex_index; // issue #9338
@@ -476,14 +527,7 @@
 
 
 			function parseBinary( data, header ) {
 			function parseBinary( data, header ) {
 
 
-				const buffer = {
-					indices: [],
-					vertices: [],
-					normals: [],
-					uvs: [],
-					faceVertexUvs: [],
-					colors: []
-				};
+				const buffer = createBuffer();
 				const little_endian = header.format === 'binary_little_endian';
 				const little_endian = header.format === 'binary_little_endian';
 				const body = new DataView( data, header.headerLength );
 				const body = new DataView( data, header.headerLength );
 				let result,
 				let result,

+ 2 - 0
examples/js/math/ConvexHull.js

@@ -102,6 +102,7 @@
 		intersectRay( ray, target ) {
 		intersectRay( ray, target ) {
 
 
 			// based on "Fast Ray-Convex Polyhedron Intersection" by Eric Haines, GRAPHICS GEMS II
 			// based on "Fast Ray-Convex Polyhedron Intersection" by Eric Haines, GRAPHICS GEMS II
+
 			const faces = this.faces;
 			const faces = this.faces;
 			let tNear = - Infinity;
 			let tNear = - Infinity;
 			let tFar = Infinity;
 			let tFar = Infinity;
@@ -133,6 +134,7 @@
 				if ( vD > 0 ) {
 				if ( vD > 0 ) {
 
 
 					// plane faces away from the ray, so this plane is a back-face
 					// plane faces away from the ray, so this plane is a back-face
+
 					tFar = Math.min( t, tFar );
 					tFar = Math.min( t, tFar );
 
 
 				} else {
 				} else {

+ 215 - 0
examples/js/postprocessing/RenderPixelatedPass.js

@@ -0,0 +1,215 @@
+( function () {
+
+	class RenderPixelatedPass extends THREE.Pass {
+
+		constructor( pixelSize, scene, camera, options = {} ) {
+
+			super();
+			this.pixelSize = pixelSize;
+			this.resolution = new THREE.Vector2();
+			this.renderResolution = new THREE.Vector2();
+			this.pixelatedMaterial = this.createPixelatedMaterial();
+			this.normalMaterial = new THREE.MeshNormalMaterial();
+			this.fsQuad = new THREE.FullScreenQuad( this.pixelatedMaterial );
+			this.scene = scene;
+			this.camera = camera;
+			this.normalEdgeStrength = options.normalEdgeStrength || 0.3;
+			this.depthEdgeStrength = options.depthEdgeStrength || 0.4;
+			this.beautyRenderTarget = new THREE.WebGLRenderTarget();
+			this.beautyRenderTarget.texture.minFilter = THREE.NearestFilter;
+			this.beautyRenderTarget.texture.magFilter = THREE.NearestFilter;
+			this.beautyRenderTarget.depthTexture = new THREE.DepthTexture();
+			this.normalRenderTarget = new THREE.WebGLRenderTarget();
+			this.normalRenderTarget.texture.minFilter = THREE.NearestFilter;
+			this.normalRenderTarget.texture.magFilter = THREE.NearestFilter;
+
+		}
+		dispose() {
+
+			this.beautyRenderTarget.dispose();
+			this.normalRenderTarget.dispose();
+			this.pixelatedMaterial.dispose();
+			this.normalMaterial.dispose();
+			this.fsQuad.dispose();
+
+		}
+		setSize( width, height ) {
+
+			this.resolution.set( width, height );
+			this.renderResolution.set( width / this.pixelSize | 0, height / this.pixelSize | 0 );
+			const {
+				x,
+				y
+			} = this.renderResolution;
+			this.beautyRenderTarget.setSize( x, y );
+			this.normalRenderTarget.setSize( x, y );
+			this.fsQuad.material.uniforms.resolution.value.set( x, y, 1 / x, 1 / y );
+
+		}
+		setPixelSize( pixelSize ) {
+
+			this.pixelSize = pixelSize;
+			this.setSize( this.resolution.x, this.resolution.y );
+
+		}
+		render( renderer, writeBuffer ) {
+
+			const uniforms = this.fsQuad.material.uniforms;
+			uniforms.normalEdgeStrength.value = this.normalEdgeStrength;
+			uniforms.depthEdgeStrength.value = this.depthEdgeStrength;
+			renderer.setRenderTarget( this.beautyRenderTarget );
+			renderer.render( this.scene, this.camera );
+			const overrideMaterial_old = this.scene.overrideMaterial;
+			renderer.setRenderTarget( this.normalRenderTarget );
+			this.scene.overrideMaterial = this.normalMaterial;
+			renderer.render( this.scene, this.camera );
+			this.scene.overrideMaterial = overrideMaterial_old;
+			uniforms.tDiffuse.value = this.beautyRenderTarget.texture;
+			uniforms.tDepth.value = this.beautyRenderTarget.depthTexture;
+			uniforms.tNormal.value = this.normalRenderTarget.texture;
+			if ( this.renderToScreen ) {
+
+				renderer.setRenderTarget( null );
+
+			} else {
+
+				renderer.setRenderTarget( writeBuffer );
+				if ( this.clear ) renderer.clear();
+
+			}
+
+			this.fsQuad.render( renderer );
+
+		}
+		createPixelatedMaterial() {
+
+			return new THREE.ShaderMaterial( {
+				uniforms: {
+					tDiffuse: {
+						value: null
+					},
+					tDepth: {
+						value: null
+					},
+					tNormal: {
+						value: null
+					},
+					resolution: {
+						value: new THREE.Vector4( this.renderResolution.x, this.renderResolution.y, 1 / this.renderResolution.x, 1 / this.renderResolution.y )
+					},
+					normalEdgeStrength: {
+						value: 0
+					},
+					depthEdgeStrength: {
+						value: 0
+					}
+				},
+				vertexShader: /* glsl */`
+				varying vec2 vUv;
+
+				void main() {
+
+					vUv = uv;
+					gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
+
+				}
+			`,
+				fragmentShader: /* glsl */`
+				uniform sampler2D tDiffuse;
+				uniform sampler2D tDepth;
+				uniform sampler2D tNormal;
+				uniform vec4 resolution;
+				uniform float normalEdgeStrength;
+				uniform float depthEdgeStrength;
+				varying vec2 vUv;
+
+				float getDepth(int x, int y) {
+
+					return texture2D( tDepth, vUv + vec2(x, y) * resolution.zw ).r;
+
+				}
+
+				vec3 getNormal(int x, int y) {
+
+					return texture2D( tNormal, vUv + vec2(x, y) * resolution.zw ).rgb * 2.0 - 1.0;
+
+				}
+
+				float depthEdgeIndicator(float depth, vec3 normal) {
+
+					float diff = 0.0;
+					diff += clamp(getDepth(1, 0) - depth, 0.0, 1.0);
+					diff += clamp(getDepth(-1, 0) - depth, 0.0, 1.0);
+					diff += clamp(getDepth(0, 1) - depth, 0.0, 1.0);
+					diff += clamp(getDepth(0, -1) - depth, 0.0, 1.0);
+					return floor(smoothstep(0.01, 0.02, diff) * 2.) / 2.;
+
+				}
+
+				float neighborNormalEdgeIndicator(int x, int y, float depth, vec3 normal) {
+
+					float depthDiff = getDepth(x, y) - depth;
+					vec3 neighborNormal = getNormal(x, y);
+
+					// Edge pixels should yield to faces who's normals are closer to the bias normal.
+					vec3 normalEdgeBias = vec3(1., 1., 1.); // This should probably be a parameter.
+					float normalDiff = dot(normal - neighborNormal, normalEdgeBias);
+					float normalIndicator = clamp(smoothstep(-.01, .01, normalDiff), 0.0, 1.0);
+
+					// Only the shallower pixel should detect the normal edge.
+					float depthIndicator = clamp(sign(depthDiff * .25 + .0025), 0.0, 1.0);
+
+					return (1.0 - dot(normal, neighborNormal)) * depthIndicator * normalIndicator;
+
+				}
+
+				float normalEdgeIndicator(float depth, vec3 normal) {
+
+					float indicator = 0.0;
+
+					indicator += neighborNormalEdgeIndicator(0, -1, depth, normal);
+					indicator += neighborNormalEdgeIndicator(0, 1, depth, normal);
+					indicator += neighborNormalEdgeIndicator(-1, 0, depth, normal);
+					indicator += neighborNormalEdgeIndicator(1, 0, depth, normal);
+
+					return step(0.1, indicator);
+
+				}
+
+				void main() {
+
+					vec4 texel = texture2D( tDiffuse, vUv );
+
+					float depth = 0.0;
+					vec3 normal = vec3(0.0);
+
+					if (depthEdgeStrength > 0.0 || normalEdgeStrength > 0.0) {
+
+						depth = getDepth(0, 0);
+						normal = getNormal(0, 0);
+
+					}
+
+					float dei = 0.0;
+					if (depthEdgeStrength > 0.0)
+						dei = depthEdgeIndicator(depth, normal);
+
+					float nei = 0.0;
+					if (normalEdgeStrength > 0.0)
+						nei = normalEdgeIndicator(depth, normal);
+
+					float Strength = dei > 0.0 ? (1.0 - depthEdgeStrength * dei) : (1.0 + normalEdgeStrength * nei);
+
+					gl_FragColor = texel * Strength;
+
+				}
+			`
+			} );
+
+		}
+
+	}
+
+	THREE.RenderPixelatedPass = RenderPixelatedPass;
+
+} )();

+ 0 - 2
examples/js/shaders/MMDToonShader.js

@@ -44,8 +44,6 @@ void RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in Geometric
 
 
 #define RE_Direct				RE_Direct_BlinnPhong
 #define RE_Direct				RE_Direct_BlinnPhong
 #define RE_IndirectDiffuse		RE_IndirectDiffuse_BlinnPhong
 #define RE_IndirectDiffuse		RE_IndirectDiffuse_BlinnPhong
-
-#define Material_LightProbeLOD( material )	(0)
 `;
 `;
 	const mmd_toon_matcap_fragment = /* glsl */`
 	const mmd_toon_matcap_fragment = /* glsl */`
 #ifdef USE_MATCAP
 #ifdef USE_MATCAP

+ 2 - 2
examples/jsm/math/ConvexHull.js

@@ -122,7 +122,7 @@ class ConvexHull {
 
 
 	intersectRay( ray, target ) {
 	intersectRay( ray, target ) {
 
 
-		// based on "Fast Ray-Convex Polyhedron Intersection"  by Eric Haines, GRAPHICS GEMS II
+		// based on "Fast Ray-Convex Polyhedron Intersection" by Eric Haines, GRAPHICS GEMS II
 
 
 		const faces = this.faces;
 		const faces = this.faces;
 
 
@@ -156,7 +156,7 @@ class ConvexHull {
 
 
 			if ( vD > 0 ) {
 			if ( vD > 0 ) {
 
 
-				//  plane faces away from the ray, so this plane is a back-face
+				// plane faces away from the ray, so this plane is a back-face
 
 
 				tFar = Math.min( t, tFar );
 				tFar = Math.min( t, tFar );
 
 

+ 1 - 1
examples/jsm/math/Octree.js

@@ -49,7 +49,7 @@ class Octree {
 
 
 		this.box = this.bounds.clone();
 		this.box = this.bounds.clone();
 
 
-		// offset small ammount to account for regular grid
+		// offset small amount to account for regular grid
 		this.box.min.x -= 0.01;
 		this.box.min.x -= 0.01;
 		this.box.min.y -= 0.01;
 		this.box.min.y -= 0.01;
 		this.box.min.z -= 0.01;
 		this.box.min.z -= 0.01;

+ 1 - 0
utils/build/rollup.examples.config.js

@@ -194,6 +194,7 @@ const files = glob.sync( '**/*.js', { cwd: jsmFolder, ignore: [
 	// dont convert new files
 	// dont convert new files
 	'exporters/KTX2Exporter.js',
 	'exporters/KTX2Exporter.js',
 	'loaders/KTX2Loader.js',
 	'loaders/KTX2Loader.js',
+	'loaders/MaterialXLoader.js'
 
 
 ] } );
 ] } );