瀏覽代碼

Examples: Convert loaders to ES6 Part II. (#21614)

Michael Herzog 4 年之前
父節點
當前提交
151a294fc1

文件差異過大導致無法顯示
+ 330 - 293
examples/js/loaders/GLTFLoader.js


+ 19 - 17
examples/js/loaders/HDRCubeTextureLoader.js

@@ -1,16 +1,16 @@
 ( function () {
 
-	var HDRCubeTextureLoader = function ( manager ) {
+	class HDRCubeTextureLoader extends THREE.Loader {
 
-		THREE.Loader.call( this, manager );
-		this.hdrLoader = new THREE.RGBELoader();
-		this.type = THREE.UnsignedByteType;
+		constructor( manager ) {
 
-	};
+			super( manager );
+			this.hdrLoader = new THREE.RGBELoader();
+			this.type = THREE.UnsignedByteType;
 
-	HDRCubeTextureLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {
-		constructor: HDRCubeTextureLoader,
-		load: function ( urls, onLoad, onProgress, onError ) {
+		}
+
+		load( urls, onLoad, onProgress, onError ) {
 
 			if ( ! Array.isArray( urls ) ) {
 
@@ -23,7 +23,7 @@
 
 			}
 
-			var texture = new THREE.CubeTexture();
+			const texture = new THREE.CubeTexture();
 			texture.type = this.type;
 
 			switch ( texture.type ) {
@@ -54,20 +54,20 @@
 
 			}
 
-			var scope = this;
-			var loaded = 0;
+			const scope = this;
+			let loaded = 0;
 
 			function loadHDRData( i, onLoad, onProgress, onError ) {
 
 				new THREE.FileLoader( scope.manager ).setPath( scope.path ).setResponseType( 'arraybuffer' ).setWithCredentials( scope.withCredentials ).load( urls[ i ], function ( buffer ) {
 
 					loaded ++;
-					var texData = scope.hdrLoader.parse( buffer );
+					const texData = scope.hdrLoader.parse( buffer );
 					if ( ! texData ) return;
 
 					if ( texData.data !== undefined ) {
 
-						var dataTexture = new THREE.DataTexture( texData.data, texData.width, texData.height );
+						const dataTexture = new THREE.DataTexture( texData.data, texData.width, texData.height );
 						dataTexture.type = texture.type;
 						dataTexture.encoding = texture.encoding;
 						dataTexture.format = texture.format;
@@ -89,7 +89,7 @@
 
 			}
 
-			for ( var i = 0; i < urls.length; i ++ ) {
+			for ( let i = 0; i < urls.length; i ++ ) {
 
 				loadHDRData( i, onLoad, onProgress, onError );
 
@@ -97,15 +97,17 @@
 
 			return texture;
 
-		},
-		setDataType: function ( value ) {
+		}
+
+		setDataType( value ) {
 
 			this.type = value;
 			this.hdrLoader.setDataType( value );
 			return this;
 
 		}
-	} );
+
+	}
 
 	THREE.HDRCubeTextureLoader = HDRCubeTextureLoader;
 

+ 38 - 43
examples/js/loaders/KTXLoader.js

@@ -7,17 +7,17 @@
  * ported from https://github.com/BabylonJS/Babylon.js/blob/master/src/Tools/babylon.khronosTextureContainer.ts
  */
 
-	var KTXLoader = function ( manager ) {
+	class KTXLoader extends THREE.CompressedTextureLoader {
 
-		THREE.CompressedTextureLoader.call( this, manager );
+		constructor( manager ) {
 
-	};
+			super( manager );
 
-	KTXLoader.prototype = Object.assign( Object.create( THREE.CompressedTextureLoader.prototype ), {
-		constructor: KTXLoader,
-		parse: function ( buffer, loadMipmaps ) {
+		}
+
+		parse( buffer, loadMipmaps ) {
 
-			var ktx = new KhronosTextureContainer( buffer, 1 );
+			const ktx = new KhronosTextureContainer( buffer, 1 );
 			return {
 				mipmaps: ktx.mipmaps( loadMipmaps ),
 				width: ktx.pixelWidth,
@@ -28,9 +28,18 @@
 			};
 
 		}
-	} );
 
-	var KhronosTextureContainer = function () {
+	}
+
+	const HEADER_LEN = 12 + 13 * 4; // identifier + header elements (not including key value meta-data pairs)
+	// load types
+
+	const COMPRESSED_2D = 0; // uses a gl.compressedTexImage2D()
+	//const COMPRESSED_3D = 1; // uses a gl.compressedTexImage3D()
+	//const TEX_2D = 2; // uses a gl.texImage2D()
+	//const TEX_3D = 3; // uses a gl.texImage3D()
+
+	class KhronosTextureContainer {
 
 		/**
 	 * @param {ArrayBuffer} arrayBuffer- contents of the KTX container file
@@ -38,7 +47,7 @@
 	 * @param {boolean} threeDExpected- provision for indicating that data should be a 3D texture, not implemented
 	 * @param {boolean} textureArrayExpected- provision for indicating that data should be a texture array, not implemented
 	 */
-		function KhronosTextureContainer( arrayBuffer, facesExpected
+		constructor( arrayBuffer, facesExpected
 			/*, threeDExpected, textureArrayExpected */
 		) {
 
@@ -46,7 +55,7 @@
 			// '´', 'K', 'T', 'X', ' ', '1', '1', 'ª', '\r', '\n', '\x1A', '\n'
 			// 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
 
-			var identifier = new Uint8Array( this.arrayBuffer, 0, 12 );
+			const identifier = new Uint8Array( this.arrayBuffer, 0, 12 );
 
 			if ( identifier[ 0 ] !== 0xAB || identifier[ 1 ] !== 0x4B || identifier[ 2 ] !== 0x54 || identifier[ 3 ] !== 0x58 || identifier[ 4 ] !== 0x20 || identifier[ 5 ] !== 0x31 || identifier[ 6 ] !== 0x31 || identifier[ 7 ] !== 0xBB || identifier[ 8 ] !== 0x0D || identifier[ 9 ] !== 0x0A || identifier[ 10 ] !== 0x1A || identifier[ 11 ] !== 0x0A ) {
 
@@ -56,10 +65,10 @@
 			} // load the reset of the header in native 32 bit uint
 
 
-			var dataSize = Uint32Array.BYTES_PER_ELEMENT;
-			var headerDataView = new DataView( this.arrayBuffer, 12, 13 * dataSize );
-			var endianness = headerDataView.getUint32( 0, true );
-			var littleEndian = endianness === 0x04030201;
+			const dataSize = Uint32Array.BYTES_PER_ELEMENT;
+			const headerDataView = new DataView( this.arrayBuffer, 12, 13 * dataSize );
+			const endianness = headerDataView.getUint32( 0, true );
+			const littleEndian = endianness === 0x04030201;
 			this.glType = headerDataView.getUint32( 1 * dataSize, littleEndian ); // must be 0 for compressed textures
 
 			this.glTypeSize = headerDataView.getUint32( 2 * dataSize, littleEndian ); // must be 1 for compressed textures
@@ -120,29 +129,28 @@
 			// would need to make this more elaborate & adjust checks above to support more than one load type
 
 
-			this.loadType = KhronosTextureContainer.COMPRESSED_2D;
-
-		} // return mipmaps for js
+			this.loadType = COMPRESSED_2D;
 
+		}
 
-		KhronosTextureContainer.prototype.mipmaps = function ( loadMipmaps ) {
+		mipmaps( loadMipmaps ) {
 
-			var mipmaps = []; // initialize width & height for level 1
+			const mipmaps = []; // initialize width & height for level 1
 
-			var dataOffset = KhronosTextureContainer.HEADER_LEN + this.bytesOfKeyValueData;
-			var width = this.pixelWidth;
-			var height = this.pixelHeight;
-			var mipmapCount = loadMipmaps ? this.numberOfMipmapLevels : 1;
+			let dataOffset = HEADER_LEN + this.bytesOfKeyValueData;
+			let width = this.pixelWidth;
+			let height = this.pixelHeight;
+			const mipmapCount = loadMipmaps ? this.numberOfMipmapLevels : 1;
 
-			for ( var level = 0; level < mipmapCount; level ++ ) {
+			for ( let level = 0; level < mipmapCount; level ++ ) {
 
-				var imageSize = new Int32Array( this.arrayBuffer, dataOffset, 1 )[ 0 ]; // size per face, since not supporting array cubemaps
+				const imageSize = new Int32Array( this.arrayBuffer, dataOffset, 1 )[ 0 ]; // size per face, since not supporting array cubemaps
 
 				dataOffset += 4; // size of the image + 4 for the imageSize field
 
-				for ( var face = 0; face < this.numberOfFaces; face ++ ) {
+				for ( let face = 0; face < this.numberOfFaces; face ++ ) {
 
-					var byteArray = new Uint8Array( this.arrayBuffer, dataOffset, imageSize );
+					const byteArray = new Uint8Array( this.arrayBuffer, dataOffset, imageSize );
 					mipmaps.push( {
 						'data': byteArray,
 						'width': width,
@@ -160,22 +168,9 @@
 
 			return mipmaps;
 
-		};
-
-		KhronosTextureContainer.HEADER_LEN = 12 + 13 * 4; // identifier + header elements (not including key value meta-data pairs)
-		// load types
-
-		KhronosTextureContainer.COMPRESSED_2D = 0; // uses a gl.compressedTexImage2D()
-
-		KhronosTextureContainer.COMPRESSED_3D = 1; // uses a gl.compressedTexImage3D()
-
-		KhronosTextureContainer.TEX_2D = 2; // uses a gl.texImage2D()
-
-		KhronosTextureContainer.TEX_3D = 3; // uses a gl.texImage3D()
-
-		return KhronosTextureContainer;
+		}
 
-	}();
+	}
 
 	THREE.KTXLoader = KTXLoader;
 

+ 168 - 163
examples/js/loaders/LWOLoader.js

@@ -12,25 +12,25 @@
  * 	http://static.lightwave3d.com/sdk/2018/html/filefmts/lwo2.html
  *
  **/
-	var lwoTree;
 
-	var LWOLoader = function ( manager, parameters ) {
+	let _lwoTree;
 
-		THREE.Loader.call( this, manager );
-		parameters = parameters || {};
-		this.resourcePath = parameters.resourcePath !== undefined ? parameters.resourcePath : '';
+	class LWOLoader extends THREE.Loader {
 
-	};
+		constructor( manager, parameters = {} ) {
 
-	LWOLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {
-		constructor: LWOLoader,
-		load: function ( url, onLoad, onProgress, onError ) {
+			super( manager );
+			this.resourcePath = parameters.resourcePath !== undefined ? parameters.resourcePath : '';
 
-			var scope = this;
-			var path = scope.path === '' ? extractParentUrl( url, 'Objects' ) : scope.path; // give the mesh a default name based on the filename
+		}
+
+		load( url, onLoad, onProgress, onError ) {
 
-			var modelName = url.split( path ).pop().split( '.' )[ 0 ];
-			var loader = new THREE.FileLoader( this.manager );
+			const scope = this;
+			const path = scope.path === '' ? extractParentUrl( url, 'Objects' ) : scope.path; // give the mesh a default name based on the filename
+
+			const modelName = url.split( path ).pop().split( '.' )[ 0 ];
+			const loader = new THREE.FileLoader( this.manager );
 			loader.setPath( scope.path );
 			loader.setResponseType( 'arraybuffer' );
 			loader.load( url, function ( buffer ) {
@@ -58,26 +58,29 @@
 
 			}, onProgress, onError );
 
-		},
-		parse: function ( iffBuffer, path, modelName ) {
+		}
 
-			lwoTree = new THREE.IFFParser().parse( iffBuffer ); // console.log( 'lwoTree', lwoTree );
+		parse( iffBuffer, path, modelName ) {
 
-			var textureLoader = new THREE.TextureLoader( this.manager ).setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin );
+			_lwoTree = new THREE.IFFParser().parse( iffBuffer ); // console.log( 'lwoTree', lwoTree );
+
+			const textureLoader = new THREE.TextureLoader( this.manager ).setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin );
 			return new LWOTreeParser( textureLoader ).parse( modelName );
 
 		}
-	} ); // Parse the lwoTree object
 
-	function LWOTreeParser( textureLoader ) {
+	} // Parse the lwoTree object
 
-		this.textureLoader = textureLoader;
 
-	}
+	class LWOTreeParser {
+
+		constructor( textureLoader ) {
 
-	LWOTreeParser.prototype = {
-		constructor: LWOTreeParser,
-		parse: function ( modelName ) {
+			this.textureLoader = textureLoader;
+
+		}
+
+		parse( modelName ) {
 
 			this.materials = new MaterialParser( this.textureLoader ).parse();
 			this.defaultLayerName = modelName;
@@ -87,56 +90,58 @@
 				meshes: this.meshes
 			};
 
-		},
+		}
 
 		parseLayers() {
 
 			// array of all meshes for building hierarchy
-			var meshes = []; // final array containing meshes with scene graph hierarchy set up
+			const meshes = []; // final array containing meshes with scene graph hierarchy set up
 
-			var finalMeshes = [];
-			var geometryParser = new GeometryParser();
-			var scope = this;
-			lwoTree.layers.forEach( function ( layer ) {
+			const finalMeshes = [];
+			const geometryParser = new GeometryParser();
+			const scope = this;
 
-				var geometry = geometryParser.parse( layer.geometry, layer );
-				var mesh = scope.parseMesh( geometry, layer );
+			_lwoTree.layers.forEach( function ( layer ) {
+
+				const geometry = geometryParser.parse( layer.geometry, layer );
+				const mesh = scope.parseMesh( geometry, layer );
 				meshes[ layer.number ] = mesh;
 				if ( layer.parent === - 1 ) finalMeshes.push( mesh ); else meshes[ layer.parent ].add( mesh );
 
 			} );
+
 			this.applyPivots( finalMeshes );
 			return finalMeshes;
 
-		},
+		}
 
 		parseMesh( geometry, layer ) {
 
-			var mesh;
-			var materials = this.getMaterials( geometry.userData.matNames, layer.geometry.type );
+			let mesh;
+			const materials = this.getMaterials( geometry.userData.matNames, layer.geometry.type );
 			this.duplicateUVs( geometry, materials );
 			if ( layer.geometry.type === 'points' ) mesh = new THREE.Points( geometry, materials ); else if ( layer.geometry.type === 'lines' ) mesh = new THREE.LineSegments( geometry, materials ); else mesh = new THREE.Mesh( geometry, materials );
 			if ( layer.name ) mesh.name = layer.name; else mesh.name = this.defaultLayerName + '_layer_' + layer.number;
 			mesh.userData.pivot = layer.pivot;
 			return mesh;
 
-		},
+		} // TODO: may need to be reversed in z to convert LWO to three.js coordinates
+
 
-		// TODO: may need to be reversed in z to convert LWO to three.js coordinates
 		applyPivots( meshes ) {
 
 			meshes.forEach( function ( mesh ) {
 
 				mesh.traverse( function ( child ) {
 
-					var pivot = child.userData.pivot;
+					const pivot = child.userData.pivot;
 					child.position.x += pivot[ 0 ];
 					child.position.y += pivot[ 1 ];
 					child.position.z += pivot[ 2 ];
 
 					if ( child.parent ) {
 
-						var parentPivot = child.parent.userData.pivot;
+						const parentPivot = child.parent.userData.pivot;
 						child.position.x -= parentPivot[ 0 ];
 						child.position.y -= parentPivot[ 1 ];
 						child.position.z -= parentPivot[ 2 ];
@@ -147,12 +152,12 @@
 
 			} );
 
-		},
+		}
 
 		getMaterials( namesArray, type ) {
 
-			var materials = [];
-			var scope = this;
+			const materials = [];
+			const scope = this;
 			namesArray.forEach( function ( name, i ) {
 
 				materials[ i ] = scope.getMaterialByName( name );
@@ -163,7 +168,7 @@
 
 				materials.forEach( function ( mat, i ) {
 
-					var spec = {
+					const spec = {
 						color: mat.color
 					};
 
@@ -185,11 +190,11 @@
 			} // if there is only one material, return that directly instead of array
 
 
-			var filtered = materials.filter( Boolean );
+			const filtered = materials.filter( Boolean );
 			if ( filtered.length === 1 ) return filtered[ 0 ];
 			return materials;
 
-		},
+		}
 
 		getMaterialByName( name ) {
 
@@ -199,12 +204,12 @@
 
 			} )[ 0 ];
 
-		},
+		} // If the material has an aoMap, duplicate UVs
+
 
-		// If the material has an aoMap, duplicate UVs
 		duplicateUVs( geometry, materials ) {
 
-			var duplicateUVs = false;
+			let duplicateUVs = false;
 
 			if ( ! Array.isArray( materials ) ) {
 
@@ -225,30 +230,30 @@
 
 		}
 
-	};
+	}
 
-	function MaterialParser( textureLoader ) {
+	class MaterialParser {
 
-		this.textureLoader = textureLoader;
+		constructor( textureLoader ) {
 
-	}
+			this.textureLoader = textureLoader;
+
+		}
 
-	MaterialParser.prototype = {
-		constructor: MaterialParser,
-		parse: function () {
+		parse() {
 
-			var materials = [];
+			const materials = [];
 			this.textures = {};
 
-			for ( var name in lwoTree.materials ) {
+			for ( const name in _lwoTree.materials ) {
 
-				if ( lwoTree.format === 'LWO3' ) {
+				if ( _lwoTree.format === 'LWO3' ) {
 
-					materials.push( this.parseMaterial( lwoTree.materials[ name ], name, lwoTree.textures ) );
+					materials.push( this.parseMaterial( _lwoTree.materials[ name ], name, _lwoTree.textures ) );
 
-				} else if ( lwoTree.format === 'LWO2' ) {
+				} else if ( _lwoTree.format === 'LWO2' ) {
 
-					materials.push( this.parseMaterialLwo2( lwoTree.materials[ name ], name, lwoTree.textures ) );
+					materials.push( this.parseMaterialLwo2( _lwoTree.materials[ name ], name, _lwoTree.textures ) );
 
 				}
 
@@ -256,45 +261,45 @@
 
 			return materials;
 
-		},
+		}
 
 		parseMaterial( materialData, name, textures ) {
 
-			var params = {
+			let params = {
 				name: name,
 				side: this.getSide( materialData.attributes ),
 				flatShading: this.getSmooth( materialData.attributes )
 			};
-			var connections = this.parseConnections( materialData.connections, materialData.nodes );
-			var maps = this.parseTextureNodes( connections.maps );
+			const connections = this.parseConnections( materialData.connections, materialData.nodes );
+			const maps = this.parseTextureNodes( connections.maps );
 			this.parseAttributeImageMaps( connections.attributes, textures, maps, materialData.maps );
-			var attributes = this.parseAttributes( connections.attributes, maps );
+			const attributes = this.parseAttributes( connections.attributes, maps );
 			this.parseEnvMap( connections, maps, attributes );
 			params = Object.assign( maps, params );
 			params = Object.assign( params, attributes );
-			var materialType = this.getMaterialType( connections.attributes );
+			const materialType = this.getMaterialType( connections.attributes );
 			return new materialType( params );
 
-		},
+		}
 
 		parseMaterialLwo2( materialData, name
 			/*, textures*/
 		) {
 
-			var params = {
+			let params = {
 				name: name,
 				side: this.getSide( materialData.attributes ),
 				flatShading: this.getSmooth( materialData.attributes )
 			};
-			var attributes = this.parseAttributes( materialData.attributes, {} );
+			const attributes = this.parseAttributes( materialData.attributes, {} );
 			params = Object.assign( params, attributes );
 			return new THREE.MeshPhongMaterial( params );
 
-		},
-
-		// Note: converting from left to right handed coords by switching x -> -x in vertices, and
+		} // Note: converting from left to right handed coords by switching x -> -x in vertices, and
 		// then switching mat THREE.FrontSide -> THREE.BackSide
 		// NB: this means that THREE.FrontSide and THREE.BackSide have been switched!
+
+
 		getSide( attributes ) {
 
 			if ( ! attributes.side ) return THREE.BackSide;
@@ -313,29 +318,29 @@
 
 			}
 
-		},
+		}
 
 		getSmooth( attributes ) {
 
 			if ( ! attributes.smooth ) return true;
 			return ! attributes.smooth;
 
-		},
+		}
 
 		parseConnections( connections, nodes ) {
 
-			var materialConnections = {
+			const materialConnections = {
 				maps: {}
 			};
-			var inputName = connections.inputName;
-			var inputNodeName = connections.inputNodeName;
-			var nodeName = connections.nodeName;
-			var scope = this;
+			const inputName = connections.inputName;
+			const inputNodeName = connections.inputNodeName;
+			const nodeName = connections.nodeName;
+			const scope = this;
 			inputName.forEach( function ( name, index ) {
 
 				if ( name === 'Material' ) {
 
-					var matNode = scope.getNodeByRefName( inputNodeName[ index ], nodes );
+					const matNode = scope.getNodeByRefName( inputNodeName[ index ], nodes );
 					materialConnections.attributes = matNode.attributes;
 					materialConnections.envMap = matNode.fileName;
 					materialConnections.name = inputNodeName[ index ];
@@ -354,28 +359,28 @@
 			} );
 			return materialConnections;
 
-		},
+		}
 
 		getNodeByRefName( refName, nodes ) {
 
-			for ( var name in nodes ) {
+			for ( const name in nodes ) {
 
 				if ( nodes[ name ].refName === refName ) return nodes[ name ];
 
 			}
 
-		},
+		}
 
 		parseTextureNodes( textureNodes ) {
 
-			var maps = {};
+			const maps = {};
 
-			for ( var name in textureNodes ) {
+			for ( const name in textureNodes ) {
 
-				var node = textureNodes[ name ];
-				var path = node.fileName;
+				const node = textureNodes[ name ];
+				const path = node.fileName;
 				if ( ! path ) return;
-				var texture = this.loadTexture( path );
+				const texture = this.loadTexture( path );
 				if ( node.widthWrappingMode !== undefined ) texture.wrapS = this.getWrappingType( node.widthWrappingMode );
 				if ( node.heightWrappingMode !== undefined ) texture.wrapT = this.getWrappingType( node.heightWrappingMode );
 
@@ -432,22 +437,22 @@
 			if ( maps.roughnessMap && maps.specularMap ) delete maps.specularMap;
 			return maps;
 
-		},
-
-		// maps can also be defined on individual material attributes, parse those here
+		} // maps can also be defined on individual material attributes, parse those here
 		// This occurs on Standard (Phong) surfaces
+
+
 		parseAttributeImageMaps( attributes, textures, maps ) {
 
-			for ( var name in attributes ) {
+			for ( const name in attributes ) {
 
-				var attribute = attributes[ name ];
+				const attribute = attributes[ name ];
 
 				if ( attribute.maps ) {
 
-					var mapData = attribute.maps[ 0 ];
-					var path = this.getTexturePathByIndex( mapData.imageIndex, textures );
+					const mapData = attribute.maps[ 0 ];
+					const path = this.getTexturePathByIndex( mapData.imageIndex, textures );
 					if ( ! path ) return;
-					var texture = this.loadTexture( path );
+					const texture = this.loadTexture( path );
 					if ( mapData.wrap !== undefined ) texture.wrapS = this.getWrappingType( mapData.wrap.w );
 					if ( mapData.wrap !== undefined ) texture.wrapT = this.getWrappingType( mapData.wrap.h );
 
@@ -501,11 +506,11 @@
 
 			}
 
-		},
+		}
 
 		parseAttributes( attributes, maps ) {
 
-			var params = {}; // don't use color data if color map is present
+			const params = {}; // don't use color data if color map is present
 
 			if ( attributes.Color && ! maps.map ) {
 
@@ -527,7 +532,7 @@
 			this.parsePhongAttributes( params, attributes, maps );
 			return params;
 
-		},
+		}
 
 		parsePhysicalAttributes( params, attributes
 			/*, maps*/
@@ -545,7 +550,7 @@
 
 			}
 
-		},
+		}
 
 		parseStandardAttributes( params, attributes, maps ) {
 
@@ -568,7 +573,7 @@
 			if ( attributes.Roughness && ! maps.roughnessMap ) params.roughness = attributes.Roughness.value;
 			if ( attributes.Metallic && ! maps.metalnessMap ) params.metalness = attributes.Metallic.value;
 
-		},
+		}
 
 		parsePhongAttributes( params, attributes, maps ) {
 
@@ -614,13 +619,13 @@
 
 			if ( params.specular && attributes.Glossiness ) params.shininess = 7 + Math.pow( 2, attributes.Glossiness.value * 12 + 2 );
 
-		},
+		}
 
 		parseEnvMap( connections, maps, attributes ) {
 
 			if ( connections.envMap ) {
 
-				var envMap = this.loadTexture( connections.envMap );
+				const envMap = this.loadTexture( connections.envMap );
 
 				if ( attributes.transparent && attributes.opacity < 0.999 ) {
 
@@ -645,36 +650,37 @@
 
 			}
 
-		},
+		} // get texture defined at top level by its index
+
 
-		// get texture defined at top level by its index
 		getTexturePathByIndex( index ) {
 
-			var fileName = '';
-			if ( ! lwoTree.textures ) return fileName;
-			lwoTree.textures.forEach( function ( texture ) {
+			let fileName = '';
+			if ( ! _lwoTree.textures ) return fileName;
+
+			_lwoTree.textures.forEach( function ( texture ) {
 
 				if ( texture.index === index ) fileName = texture.fileName;
 
 			} );
+
 			return fileName;
 
-		},
+		}
 
 		loadTexture( path ) {
 
 			if ( ! path ) return null;
-			var texture;
-			texture = this.textureLoader.load( path, undefined, undefined, function () {
+			const texture = this.textureLoader.load( path, undefined, undefined, function () {
 
 				console.warn( 'LWOLoader: non-standard resource hierarchy. Use \`resourcePath\` parameter to specify root content directory.' );
 
 			} );
 			return texture;
 
-		},
+		} // 0 = Reset, 1 = Repeat, 2 = Mirror, 3 = Edge
+
 
-		// 0 = Reset, 1 = Repeat, 2 = Mirror, 3 = Edge
 		getWrappingType( num ) {
 
 			switch ( num ) {
@@ -694,7 +700,7 @@
 
 			}
 
-		},
+		}
 
 		getMaterialType( nodeData ) {
 
@@ -704,42 +710,39 @@
 
 		}
 
-	};
-
-	function GeometryParser() {}
+	}
 
-	GeometryParser.prototype = {
-		constructor: GeometryParser,
+	class GeometryParser {
 
 		parse( geoData, layer ) {
 
-			var geometry = new THREE.BufferGeometry();
+			const geometry = new THREE.BufferGeometry();
 			geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( geoData.points, 3 ) );
-			var indices = this.splitIndices( geoData.vertexIndices, geoData.polygonDimensions );
+			const indices = this.splitIndices( geoData.vertexIndices, geoData.polygonDimensions );
 			geometry.setIndex( indices );
 			this.parseGroups( geometry, geoData );
 			geometry.computeVertexNormals();
 			this.parseUVs( geometry, layer, indices );
 			this.parseMorphTargets( geometry, layer, indices ); // TODO: z may need to be reversed to account for coordinate system change
 
-			geometry.translate( - layer.pivot[ 0 ], - layer.pivot[ 1 ], - layer.pivot[ 2 ] ); // var userData = geometry.userData;
+			geometry.translate( - layer.pivot[ 0 ], - layer.pivot[ 1 ], - layer.pivot[ 2 ] ); // let userData = geometry.userData;
 			// geometry = geometry.toNonIndexed()
 			// geometry.userData = userData;
 
 			return geometry;
 
-		},
+		} // split quads into tris
+
 
-		// split quads into tris
 		splitIndices( indices, polygonDimensions ) {
 
-			var remappedIndices = [];
-			var i = 0;
+			const remappedIndices = [];
+			let i = 0;
 			polygonDimensions.forEach( function ( dim ) {
 
 				if ( dim < 4 ) {
 
-					for ( var k = 0; k < dim; k ++ ) remappedIndices.push( indices[ i + k ] );
+					for ( let k = 0; k < dim; k ++ ) remappedIndices.push( indices[ i + k ] );
 
 				} else if ( dim === 4 ) {
 
@@ -747,7 +750,7 @@
 
 				} else if ( dim > 4 ) {
 
-					for ( var k = 1; k < dim - 1; k ++ ) {
+					for ( let k = 1; k < dim - 1; k ++ ) {
 
 						remappedIndices.push( indices[ i ], indices[ i + k ], indices[ i + k + 1 ] );
 
@@ -762,34 +765,35 @@
 			} );
 			return remappedIndices;
 
-		},
+		} // NOTE: currently ignoring poly indices and assuming that they are intelligently ordered
+
 
-		// NOTE: currently ignoring poly indices and assuming that they are intelligently ordered
 		parseGroups( geometry, geoData ) {
 
-			var tags = lwoTree.tags;
-			var matNames = [];
-			var elemSize = 3;
+			const tags = _lwoTree.tags;
+			const matNames = [];
+			let elemSize = 3;
 			if ( geoData.type === 'lines' ) elemSize = 2;
 			if ( geoData.type === 'points' ) elemSize = 1;
-			var remappedIndices = this.splitMaterialIndices( geoData.polygonDimensions, geoData.materialIndices );
-			var indexNum = 0; // create new indices in numerical order
+			const remappedIndices = this.splitMaterialIndices( geoData.polygonDimensions, geoData.materialIndices );
+			let indexNum = 0; // create new indices in numerical order
 
-			var indexPairs = {}; // original indices mapped to numerical indices
+			const indexPairs = {}; // original indices mapped to numerical indices
 
-			var prevMaterialIndex;
-			var prevStart = 0;
-			var currentCount = 0;
+			let prevMaterialIndex;
+			let materialIndex;
+			let prevStart = 0;
+			let currentCount = 0;
 
-			for ( var i = 0; i < remappedIndices.length; i += 2 ) {
+			for ( let i = 0; i < remappedIndices.length; i += 2 ) {
 
-				var materialIndex = remappedIndices[ i + 1 ];
+				materialIndex = remappedIndices[ i + 1 ];
 				if ( i === 0 ) matNames[ indexNum ] = tags[ materialIndex ];
 				if ( prevMaterialIndex === undefined ) prevMaterialIndex = materialIndex;
 
 				if ( materialIndex !== prevMaterialIndex ) {
 
-					var currentIndex;
+					let currentIndex;
 
 					if ( indexPairs[ tags[ prevMaterialIndex ] ] ) {
 
@@ -818,7 +822,7 @@
 
 			if ( geometry.groups.length > 0 ) {
 
-				var currentIndex;
+				let currentIndex;
 
 				if ( indexPairs[ tags[ materialIndex ] ] ) {
 
@@ -839,11 +843,11 @@
 
 			geometry.userData.matNames = matNames;
 
-		},
+		}
 
 		splitMaterialIndices( polygonDimensions, indices ) {
 
-			var remappedIndices = [];
+			const remappedIndices = [];
 			polygonDimensions.forEach( function ( dim, i ) {
 
 				if ( dim <= 3 ) {
@@ -857,7 +861,7 @@
 				} else {
 
 					// ignore > 4 for now
-					for ( var k = 0; k < dim - 2; k ++ ) {
+					for ( let k = 0; k < dim - 2; k ++ ) {
 
 						remappedIndices.push( indices[ i * 2 ], indices[ i * 2 + 1 ] );
 
@@ -868,9 +872,7 @@
 			} );
 			return remappedIndices;
 
-		},
-
-		// UV maps:
+		} // UV maps:
 		// 1: are defined via index into an array of points, not into a geometry
 		// - the geometry is also defined by an index into this array, but the indexes may not match
 		// 2: there can be any number of UV maps for a single geometry. Here these are combined,
@@ -879,19 +881,21 @@
 		// 4: UV maps can be VMAP or VMAD (discontinuous, to allow for seams). In practice, most
 		// UV maps are defined as partially VMAP and partially VMAD
 		// VMADs are currently not supported
+
+
 		parseUVs( geometry, layer ) {
 
 			// start by creating a UV map set to zero for the whole geometry
-			var remappedUVs = Array.from( Array( geometry.attributes.position.count * 2 ), function () {
+			const remappedUVs = Array.from( Array( geometry.attributes.position.count * 2 ), function () {
 
 				return 0;
 
 			} );
 
-			for ( var name in layer.uvs ) {
+			for ( const name in layer.uvs ) {
 
-				var uvs = layer.uvs[ name ].uvs;
-				var uvIndices = layer.uvs[ name ].uvIndices;
+				const uvs = layer.uvs[ name ].uvs;
+				const uvIndices = layer.uvs[ name ].uvIndices;
 				uvIndices.forEach( function ( i, j ) {
 
 					remappedUVs[ i * 2 ] = uvs[ j * 2 ];
@@ -903,19 +907,19 @@
 
 			geometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( remappedUVs, 2 ) );
 
-		},
+		}
 
 		parseMorphTargets( geometry, layer ) {
 
-			var num = 0;
+			let num = 0;
 
-			for ( var name in layer.morphTargets ) {
+			for ( const name in layer.morphTargets ) {
 
-				var remappedPoints = geometry.attributes.position.array.slice();
+				const remappedPoints = geometry.attributes.position.array.slice();
 				if ( ! geometry.morphAttributes.position ) geometry.morphAttributes.position = [];
-				var morphPoints = layer.morphTargets[ name ].points;
-				var morphIndices = layer.morphTargets[ name ].indices;
-				var type = layer.morphTargets[ name ].type;
+				const morphPoints = layer.morphTargets[ name ].points;
+				const morphIndices = layer.morphTargets[ name ].indices;
+				const type = layer.morphTargets[ name ].type;
 				morphIndices.forEach( function ( i, j ) {
 
 					if ( type === 'relative' ) {
@@ -943,11 +947,12 @@
 
 		}
 
-	}; // ************** UTILITY FUNCTIONS **************
+	} // ************** UTILITY FUNCTIONS **************
+
 
 	function extractParentUrl( url, dir ) {
 
-		var index = url.indexOf( dir );
+		const index = url.indexOf( dir );
 		if ( index === - 1 ) return './';
 		return url.substr( 0, index );
 

+ 103 - 89
examples/js/loaders/MTLLoader.js

@@ -4,15 +4,13 @@
  * Loads a Wavefront .mtl file specifying materials
  */
 
-	var MTLLoader = function ( manager ) {
+	class MTLLoader extends THREE.Loader {
 
-		THREE.Loader.call( this, manager );
+		constructor( manager ) {
 
-	};
-
-	MTLLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {
-		constructor: MTLLoader,
+			super( manager );
 
+		}
 		/**
 	 * Loads and parses a MTL asset from a URL.
 	 *
@@ -26,11 +24,13 @@
 	 * @note In order for relative texture references to resolve correctly
 	 * you must call setResourcePath() explicitly prior to load.
 	 */
-		load: function ( url, onLoad, onProgress, onError ) {
 
-			var scope = this;
-			var path = this.path === '' ? THREE.LoaderUtils.extractUrlBase( url ) : this.path;
-			var loader = new THREE.FileLoader( this.manager );
+
+		load( url, onLoad, onProgress, onError ) {
+
+			const scope = this;
+			const path = this.path === '' ? THREE.LoaderUtils.extractUrlBase( url ) : this.path;
+			const loader = new THREE.FileLoader( this.manager );
 			loader.setPath( this.path );
 			loader.setRequestHeader( this.requestHeader );
 			loader.setWithCredentials( this.withCredentials );
@@ -58,35 +58,37 @@
 
 			}, onProgress, onError );
 
-		},
-		setMaterialOptions: function ( value ) {
+		}
+
+		setMaterialOptions( value ) {
 
 			this.materialOptions = value;
 			return this;
 
-		},
-
+		}
 		/**
 	 * Parses a MTL file.
 	 *
 	 * @param {String} text - Content of MTL file
-	 * @return {MTLLoader.MaterialCreator}
+	 * @return {MaterialCreator}
 	 *
 	 * @see setPath setResourcePath
 	 *
 	 * @note In order for relative texture references to resolve correctly
 	 * you must call setResourcePath() explicitly prior to parse.
 	 */
-		parse: function ( text, path ) {
 
-			var lines = text.split( '\n' );
-			var info = {};
-			var delimiter_pattern = /\s+/;
-			var materialsInfo = {};
 
-			for ( var i = 0; i < lines.length; i ++ ) {
+		parse( text, path ) {
+
+			const lines = text.split( '\n' );
+			let info = {};
+			const delimiter_pattern = /\s+/;
+			const materialsInfo = {};
+
+			for ( let i = 0; i < lines.length; i ++ ) {
 
-				var line = lines[ i ];
+				let line = lines[ i ];
 				line = line.trim();
 
 				if ( line.length === 0 || line.charAt( 0 ) === '#' ) {
@@ -96,10 +98,10 @@
 
 				}
 
-				var pos = line.indexOf( ' ' );
-				var key = pos >= 0 ? line.substring( 0, pos ) : line;
+				const pos = line.indexOf( ' ' );
+				let key = pos >= 0 ? line.substring( 0, pos ) : line;
 				key = key.toLowerCase();
-				var value = pos >= 0 ? line.substring( pos + 1 ) : '';
+				let value = pos >= 0 ? line.substring( pos + 1 ) : '';
 				value = value.trim();
 
 				if ( key === 'newmtl' ) {
@@ -114,7 +116,7 @@
 
 					if ( key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke' ) {
 
-						var ss = value.split( delimiter_pattern, 3 );
+						const ss = value.split( delimiter_pattern, 3 );
 						info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ];
 
 					} else {
@@ -127,14 +129,15 @@
 
 			}
 
-			var materialCreator = new MTLLoader.MaterialCreator( this.resourcePath || path, this.materialOptions );
+			const materialCreator = new MaterialCreator( this.resourcePath || path, this.materialOptions );
 			materialCreator.setCrossOrigin( this.crossOrigin );
 			materialCreator.setManager( this.manager );
 			materialCreator.setMaterials( materialsInfo );
 			return materialCreator;
 
 		}
-	} );
+
+	}
 	/**
  * Create a new MTLLoader.MaterialCreator
  * @param baseUrl - Url relative to which textures are loaded
@@ -150,58 +153,62 @@
  * @constructor
  */
 
-	MTLLoader.MaterialCreator = function ( baseUrl, options ) {
 
-		this.baseUrl = baseUrl || '';
-		this.options = options;
-		this.materialsInfo = {};
-		this.materials = {};
-		this.materialsArray = [];
-		this.nameLookup = {};
-		this.side = this.options && this.options.side ? this.options.side : THREE.FrontSide;
-		this.wrap = this.options && this.options.wrap ? this.options.wrap : THREE.RepeatWrapping;
+	class MaterialCreator {
 
-	};
+		constructor( baseUrl = '', options = {} ) {
 
-	MTLLoader.MaterialCreator.prototype = {
-		constructor: MTLLoader.MaterialCreator,
-		crossOrigin: 'anonymous',
-		setCrossOrigin: function ( value ) {
+			this.baseUrl = baseUrl;
+			this.options = options;
+			this.materialsInfo = {};
+			this.materials = {};
+			this.materialsArray = [];
+			this.nameLookup = {};
+			this.crossOrigin = 'anonymous';
+			this.side = this.options.side !== undefined ? this.options.side : THREE.FrontSide;
+			this.wrap = this.options.wrap !== undefined ? this.options.wrap : THREE.RepeatWrapping;
+
+		}
+
+		setCrossOrigin( value ) {
 
 			this.crossOrigin = value;
 			return this;
 
-		},
-		setManager: function ( value ) {
+		}
+
+		setManager( value ) {
 
 			this.manager = value;
 
-		},
-		setMaterials: function ( materialsInfo ) {
+		}
+
+		setMaterials( materialsInfo ) {
 
 			this.materialsInfo = this.convert( materialsInfo );
 			this.materials = {};
 			this.materialsArray = [];
 			this.nameLookup = {};
 
-		},
-		convert: function ( materialsInfo ) {
+		}
+
+		convert( materialsInfo ) {
 
 			if ( ! this.options ) return materialsInfo;
-			var converted = {};
+			const converted = {};
 
-			for ( var mn in materialsInfo ) {
+			for ( const mn in materialsInfo ) {
 
 				// Convert materials info into normalized form based on options
-				var mat = materialsInfo[ mn ];
-				var covmat = {};
+				const mat = materialsInfo[ mn ];
+				const covmat = {};
 				converted[ mn ] = covmat;
 
-				for ( var prop in mat ) {
+				for ( const prop in mat ) {
 
-					var save = true;
-					var value = mat[ prop ];
-					var lprop = prop.toLowerCase();
+					let save = true;
+					let value = mat[ prop ];
+					const lprop = prop.toLowerCase();
 
 					switch ( lprop ) {
 
@@ -245,26 +252,29 @@
 
 			return converted;
 
-		},
-		preload: function () {
+		}
+
+		preload() {
 
-			for ( var mn in this.materialsInfo ) {
+			for ( const mn in this.materialsInfo ) {
 
 				this.create( mn );
 
 			}
 
-		},
-		getIndex: function ( materialName ) {
+		}
+
+		getIndex( materialName ) {
 
 			return this.nameLookup[ materialName ];
 
-		},
-		getAsArray: function () {
+		}
+
+		getAsArray() {
 
-			var index = 0;
+			let index = 0;
 
-			for ( var mn in this.materialsInfo ) {
+			for ( const mn in this.materialsInfo ) {
 
 				this.materialsArray[ index ] = this.create( mn );
 				this.nameLookup[ mn ] = index;
@@ -274,8 +284,9 @@
 
 			return this.materialsArray;
 
-		},
-		create: function ( materialName ) {
+		}
+
+		create( materialName ) {
 
 			if ( this.materials[ materialName ] === undefined ) {
 
@@ -285,13 +296,14 @@
 
 			return this.materials[ materialName ];
 
-		},
-		createMaterial_: function ( materialName ) {
+		}
+
+		createMaterial_( materialName ) {
 
 			// Create material
-			var scope = this;
-			var mat = this.materialsInfo[ materialName ];
-			var params = {
+			const scope = this;
+			const mat = this.materialsInfo[ materialName ];
+			const params = {
 				name: materialName,
 				side: this.side
 			};
@@ -309,8 +321,8 @@
 
 				if ( params[ mapType ] ) return; // Keep the first encountered texture
 
-				var texParams = scope.getTextureParams( value, params );
-				var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) );
+				const texParams = scope.getTextureParams( value, params );
+				const map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) );
 				map.repeat.copy( texParams.scale );
 				map.offset.copy( texParams.offset );
 				map.wrapS = scope.wrap;
@@ -319,10 +331,10 @@
 
 			}
 
-			for ( var prop in mat ) {
+			for ( const prop in mat ) {
 
-				var value = mat[ prop ];
-				var n;
+				const value = mat[ prop ];
+				let n;
 				if ( value === '' ) continue;
 
 				switch ( prop.toLowerCase() ) {
@@ -415,15 +427,16 @@
 			this.materials[ materialName ] = new THREE.MeshPhongMaterial( params );
 			return this.materials[ materialName ];
 
-		},
-		getTextureParams: function ( value, matParams ) {
+		}
 
-			var texParams = {
+		getTextureParams( value, matParams ) {
+
+			const texParams = {
 				scale: new THREE.Vector2( 1, 1 ),
 				offset: new THREE.Vector2( 0, 0 )
 			};
-			var items = value.split( /\s+/ );
-			var pos;
+			const items = value.split( /\s+/ );
+			let pos;
 			pos = items.indexOf( '-bm' );
 
 			if ( pos >= 0 ) {
@@ -454,12 +467,12 @@
 			texParams.url = items.join( ' ' ).trim();
 			return texParams;
 
-		},
-		loadTexture: function ( url, mapping, onLoad, onProgress, onError ) {
+		}
+
+		loadTexture( url, mapping, onLoad, onProgress, onError ) {
 
-			var texture;
-			var manager = this.manager !== undefined ? this.manager : THREE.DefaultLoadingManager;
-			var loader = manager.getHandler( url );
+			const manager = this.manager !== undefined ? this.manager : THREE.DefaultLoadingManager;
+			let loader = manager.getHandler( url );
 
 			if ( loader === null ) {
 
@@ -468,12 +481,13 @@
 			}
 
 			if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin );
-			texture = loader.load( url, onLoad, onProgress, onError );
+			const texture = loader.load( url, onLoad, onProgress, onError );
 			if ( mapping !== undefined ) texture.mapping = mapping;
 			return texture;
 
 		}
-	};
+
+	}
 
 	THREE.MTLLoader = MTLLoader;
 

+ 515 - 505
examples/js/loaders/OBJLoader.js

@@ -1,575 +1,587 @@
 ( function () {
 
-	var OBJLoader = function () {
+	const _object_pattern = /^[og]\s*(.+)?/; // mtllib file_reference
 
-		// o object_name | g group_name
-		var object_pattern = /^[og]\s*(.+)?/; // mtllib file_reference
+	const _material_library_pattern = /^mtllib /; // usemtl material_name
 
-		var material_library_pattern = /^mtllib /; // usemtl material_name
+	const _material_use_pattern = /^usemtl /; // usemap map_name
 
-		var material_use_pattern = /^usemtl /; // usemap map_name
+	const _map_use_pattern = /^usemap /;
 
-		var map_use_pattern = /^usemap /;
-		var vA = new THREE.Vector3();
-		var vB = new THREE.Vector3();
-		var vC = new THREE.Vector3();
-		var ab = new THREE.Vector3();
-		var cb = new THREE.Vector3();
+	const _vA = new THREE.Vector3();
 
-		function ParserState() {
+	const _vB = new THREE.Vector3();
 
-			var state = {
-				objects: [],
-				object: {},
-				vertices: [],
-				normals: [],
-				colors: [],
-				uvs: [],
-				materials: {},
-				materialLibraries: [],
-				startObject: function ( name, fromDeclaration ) {
+	const _vC = new THREE.Vector3();
 
-					// If the current object (initial from reset) is not from a g/o declaration in the parsed
-					// file. We need to use it for the first parsed g/o to keep things in sync.
-					if ( this.object && this.object.fromDeclaration === false ) {
+	const _ab = new THREE.Vector3();
 
-						this.object.name = name;
-						this.object.fromDeclaration = fromDeclaration !== false;
-						return;
+	const _cb = new THREE.Vector3();
 
-					}
+	function ParserState() {
 
-					var previousMaterial = this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined;
+		const state = {
+			objects: [],
+			object: {},
+			vertices: [],
+			normals: [],
+			colors: [],
+			uvs: [],
+			materials: {},
+			materialLibraries: [],
+			startObject: function ( name, fromDeclaration ) {
 
-					if ( this.object && typeof this.object._finalize === 'function' ) {
+				// If the current object (initial from reset) is not from a g/o declaration in the parsed
+				// file. We need to use it for the first parsed g/o to keep things in sync.
+				if ( this.object && this.object.fromDeclaration === false ) {
 
-						this.object._finalize( true );
+					this.object.name = name;
+					this.object.fromDeclaration = fromDeclaration !== false;
+					return;
 
-					}
+				}
 
-					this.object = {
-						name: name || '',
-						fromDeclaration: fromDeclaration !== false,
-						geometry: {
-							vertices: [],
-							normals: [],
-							colors: [],
-							uvs: [],
-							hasUVIndices: false
-						},
-						materials: [],
-						smooth: true,
-						startMaterial: function ( name, libraries ) {
+				const previousMaterial = this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined;
 
-							var previous = this._finalize( false ); // New usemtl declaration overwrites an inherited material, except if faces were declared
-							// after the material, then it must be preserved for proper MultiMaterial continuation.
+				if ( this.object && typeof this.object._finalize === 'function' ) {
 
+					this.object._finalize( true );
 
-							if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) {
+				}
 
-								this.materials.splice( previous.index, 1 );
+				this.object = {
+					name: name || '',
+					fromDeclaration: fromDeclaration !== false,
+					geometry: {
+						vertices: [],
+						normals: [],
+						colors: [],
+						uvs: [],
+						hasUVIndices: false
+					},
+					materials: [],
+					smooth: true,
+					startMaterial: function ( name, libraries ) {
 
-							}
+						const previous = this._finalize( false ); // New usemtl declaration overwrites an inherited material, except if faces were declared
+						// after the material, then it must be preserved for proper MultiMaterial continuation.
 
-							var material = {
-								index: this.materials.length,
-								name: name || '',
-								mtllib: Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '',
-								smooth: previous !== undefined ? previous.smooth : this.smooth,
-								groupStart: previous !== undefined ? previous.groupEnd : 0,
-								groupEnd: - 1,
-								groupCount: - 1,
-								inherited: false,
-								clone: function ( index ) {
-
-									var cloned = {
-										index: typeof index === 'number' ? index : this.index,
-										name: this.name,
-										mtllib: this.mtllib,
-										smooth: this.smooth,
-										groupStart: 0,
-										groupEnd: - 1,
-										groupCount: - 1,
-										inherited: false
-									};
-									cloned.clone = this.clone.bind( cloned );
-									return cloned;
 
-								}
-							};
-							this.materials.push( material );
-							return material;
+						if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) {
 
-						},
-						currentMaterial: function () {
+							this.materials.splice( previous.index, 1 );
 
-							if ( this.materials.length > 0 ) {
+						}
 
-								return this.materials[ this.materials.length - 1 ];
+						const material = {
+							index: this.materials.length,
+							name: name || '',
+							mtllib: Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '',
+							smooth: previous !== undefined ? previous.smooth : this.smooth,
+							groupStart: previous !== undefined ? previous.groupEnd : 0,
+							groupEnd: - 1,
+							groupCount: - 1,
+							inherited: false,
+							clone: function ( index ) {
+
+								const cloned = {
+									index: typeof index === 'number' ? index : this.index,
+									name: this.name,
+									mtllib: this.mtllib,
+									smooth: this.smooth,
+									groupStart: 0,
+									groupEnd: - 1,
+									groupCount: - 1,
+									inherited: false
+								};
+								cloned.clone = this.clone.bind( cloned );
+								return cloned;
 
 							}
+						};
+						this.materials.push( material );
+						return material;
 
-							return undefined;
+					},
+					currentMaterial: function () {
 
-						},
-						_finalize: function ( end ) {
+						if ( this.materials.length > 0 ) {
 
-							var lastMultiMaterial = this.currentMaterial();
+							return this.materials[ this.materials.length - 1 ];
 
-							if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) {
-
-								lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;
-								lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;
-								lastMultiMaterial.inherited = false;
+						}
 
-							} // Ignore objects tail materials if no face declarations followed them before a new o/g started.
+						return undefined;
 
+					},
+					_finalize: function ( end ) {
 
-							if ( end && this.materials.length > 1 ) {
+						const lastMultiMaterial = this.currentMaterial();
 
-								for ( var mi = this.materials.length - 1; mi >= 0; mi -- ) {
+						if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) {
 
-									if ( this.materials[ mi ].groupCount <= 0 ) {
+							lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;
+							lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;
+							lastMultiMaterial.inherited = false;
 
-										this.materials.splice( mi, 1 );
+						} // Ignore objects tail materials if no face declarations followed them before a new o/g started.
 
-									}
 
-								}
+						if ( end && this.materials.length > 1 ) {
 
-							} // Guarantee at least one empty material, this makes the creation later more straight forward.
+							for ( let mi = this.materials.length - 1; mi >= 0; mi -- ) {
 
+								if ( this.materials[ mi ].groupCount <= 0 ) {
 
-							if ( end && this.materials.length === 0 ) {
+									this.materials.splice( mi, 1 );
 
-								this.materials.push( {
-									name: '',
-									smooth: this.smooth
-								} );
+								}
 
 							}
 
-							return lastMultiMaterial;
+						} // Guarantee at least one empty material, this makes the creation later more straight forward.
 
-						}
-					}; // Inherit previous objects material.
-					// Spec tells us that a declared material must be set to all objects until a new material is declared.
-					// If a usemtl declaration is encountered while this new object is being parsed, it will
-					// overwrite the inherited material. Exception being that there was already face declarations
-					// to the inherited material, then it will be preserved for proper MultiMaterial continuation.
 
-					if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) {
+						if ( end && this.materials.length === 0 ) {
 
-						var declared = previousMaterial.clone( 0 );
-						declared.inherited = true;
-						this.object.materials.push( declared );
+							this.materials.push( {
+								name: '',
+								smooth: this.smooth
+							} );
+
+						}
+
+						return lastMultiMaterial;
 
 					}
+				}; // Inherit previous objects material.
+				// Spec tells us that a declared material must be set to all objects until a new material is declared.
+				// If a usemtl declaration is encountered while this new object is being parsed, it will
+				// overwrite the inherited material. Exception being that there was already face declarations
+				// to the inherited material, then it will be preserved for proper MultiMaterial continuation.
 
-					this.objects.push( this.object );
+				if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) {
 
-				},
-				finalize: function () {
+					const declared = previousMaterial.clone( 0 );
+					declared.inherited = true;
+					this.object.materials.push( declared );
 
-					if ( this.object && typeof this.object._finalize === 'function' ) {
+				}
 
-						this.object._finalize( true );
+				this.objects.push( this.object );
 
-					}
+			},
+			finalize: function () {
 
-				},
-				parseVertexIndex: function ( value, len ) {
+				if ( this.object && typeof this.object._finalize === 'function' ) {
 
-					var index = parseInt( value, 10 );
-					return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
+					this.object._finalize( true );
 
-				},
-				parseNormalIndex: function ( value, len ) {
+				}
 
-					var index = parseInt( value, 10 );
-					return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
+			},
+			parseVertexIndex: function ( value, len ) {
 
-				},
-				parseUVIndex: function ( value, len ) {
-
-					var index = parseInt( value, 10 );
-					return ( index >= 0 ? index - 1 : index + len / 2 ) * 2;
+				const index = parseInt( value, 10 );
+				return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
 
-				},
-				addVertex: function ( a, b, c ) {
+			},
+			parseNormalIndex: function ( value, len ) {
 
-					var src = this.vertices;
-					var dst = this.object.geometry.vertices;
-					dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
-					dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
-					dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
+				const index = parseInt( value, 10 );
+				return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
 
-				},
-				addVertexPoint: function ( a ) {
+			},
+			parseUVIndex: function ( value, len ) {
 
-					var src = this.vertices;
-					var dst = this.object.geometry.vertices;
-					dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
+				const index = parseInt( value, 10 );
+				return ( index >= 0 ? index - 1 : index + len / 2 ) * 2;
 
-				},
-				addVertexLine: function ( a ) {
+			},
+			addVertex: function ( a, b, c ) {
 
-					var src = this.vertices;
-					var dst = this.object.geometry.vertices;
-					dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
+				const src = this.vertices;
+				const dst = this.object.geometry.vertices;
+				dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
+				dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
+				dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
 
-				},
-				addNormal: function ( a, b, c ) {
+			},
+			addVertexPoint: function ( a ) {
 
-					var src = this.normals;
-					var dst = this.object.geometry.normals;
-					dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
-					dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
-					dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
+				const src = this.vertices;
+				const dst = this.object.geometry.vertices;
+				dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
 
-				},
-				addFaceNormal: function ( a, b, c ) {
+			},
+			addVertexLine: function ( a ) {
 
-					var src = this.vertices;
-					var dst = this.object.geometry.normals;
-					vA.fromArray( src, a );
-					vB.fromArray( src, b );
-					vC.fromArray( src, c );
-					cb.subVectors( vC, vB );
-					ab.subVectors( vA, vB );
-					cb.cross( ab );
-					cb.normalize();
-					dst.push( cb.x, cb.y, cb.z );
-					dst.push( cb.x, cb.y, cb.z );
-					dst.push( cb.x, cb.y, cb.z );
+				const src = this.vertices;
+				const dst = this.object.geometry.vertices;
+				dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
 
-				},
-				addColor: function ( a, b, c ) {
+			},
+			addNormal: function ( a, b, c ) {
 
-					var src = this.colors;
-					var dst = this.object.geometry.colors;
-					if ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
-					if ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
-					if ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
+				const src = this.normals;
+				const dst = this.object.geometry.normals;
+				dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
+				dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
+				dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
 
-				},
-				addUV: function ( a, b, c ) {
+			},
+			addFaceNormal: function ( a, b, c ) {
 
-					var src = this.uvs;
-					var dst = this.object.geometry.uvs;
-					dst.push( src[ a + 0 ], src[ a + 1 ] );
-					dst.push( src[ b + 0 ], src[ b + 1 ] );
-					dst.push( src[ c + 0 ], src[ c + 1 ] );
+				const src = this.vertices;
+				const dst = this.object.geometry.normals;
 
-				},
-				addDefaultUV: function () {
+				_vA.fromArray( src, a );
 
-					var dst = this.object.geometry.uvs;
-					dst.push( 0, 0 );
-					dst.push( 0, 0 );
-					dst.push( 0, 0 );
+				_vB.fromArray( src, b );
 
-				},
-				addUVLine: function ( a ) {
+				_vC.fromArray( src, c );
 
-					var src = this.uvs;
-					var dst = this.object.geometry.uvs;
-					dst.push( src[ a + 0 ], src[ a + 1 ] );
+				_cb.subVectors( _vC, _vB );
 
-				},
-				addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) {
-
-					var vLen = this.vertices.length;
-					var ia = this.parseVertexIndex( a, vLen );
-					var ib = this.parseVertexIndex( b, vLen );
-					var ic = this.parseVertexIndex( c, vLen );
-					this.addVertex( ia, ib, ic );
-					this.addColor( ia, ib, ic ); // normals
-
-					if ( na !== undefined && na !== '' ) {
-
-						var nLen = this.normals.length;
-						ia = this.parseNormalIndex( na, nLen );
-						ib = this.parseNormalIndex( nb, nLen );
-						ic = this.parseNormalIndex( nc, nLen );
-						this.addNormal( ia, ib, ic );
+				_ab.subVectors( _vA, _vB );
 
-					} else {
+				_cb.cross( _ab );
 
-						this.addFaceNormal( ia, ib, ic );
+				_cb.normalize();
 
-					} // uvs
+				dst.push( _cb.x, _cb.y, _cb.z );
+				dst.push( _cb.x, _cb.y, _cb.z );
+				dst.push( _cb.x, _cb.y, _cb.z );
 
+			},
+			addColor: function ( a, b, c ) {
 
-					if ( ua !== undefined && ua !== '' ) {
+				const src = this.colors;
+				const dst = this.object.geometry.colors;
+				if ( src[ a ] !== undefined ) dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
+				if ( src[ b ] !== undefined ) dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
+				if ( src[ c ] !== undefined ) dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
 
-						var uvLen = this.uvs.length;
-						ia = this.parseUVIndex( ua, uvLen );
-						ib = this.parseUVIndex( ub, uvLen );
-						ic = this.parseUVIndex( uc, uvLen );
-						this.addUV( ia, ib, ic );
-						this.object.geometry.hasUVIndices = true;
+			},
+			addUV: function ( a, b, c ) {
 
-					} else {
+				const src = this.uvs;
+				const dst = this.object.geometry.uvs;
+				dst.push( src[ a + 0 ], src[ a + 1 ] );
+				dst.push( src[ b + 0 ], src[ b + 1 ] );
+				dst.push( src[ c + 0 ], src[ c + 1 ] );
 
-						// add placeholder values (for inconsistent face definitions)
-						this.addDefaultUV();
+			},
+			addDefaultUV: function () {
 
-					}
+				const dst = this.object.geometry.uvs;
+				dst.push( 0, 0 );
+				dst.push( 0, 0 );
+				dst.push( 0, 0 );
 
-				},
-				addPointGeometry: function ( vertices ) {
+			},
+			addUVLine: function ( a ) {
 
-					this.object.geometry.type = 'Points';
-					var vLen = this.vertices.length;
+				const src = this.uvs;
+				const dst = this.object.geometry.uvs;
+				dst.push( src[ a + 0 ], src[ a + 1 ] );
 
-					for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) {
+			},
+			addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) {
 
-						var index = this.parseVertexIndex( vertices[ vi ], vLen );
-						this.addVertexPoint( index );
-						this.addColor( index );
+				const vLen = this.vertices.length;
+				let ia = this.parseVertexIndex( a, vLen );
+				let ib = this.parseVertexIndex( b, vLen );
+				let ic = this.parseVertexIndex( c, vLen );
+				this.addVertex( ia, ib, ic );
+				this.addColor( ia, ib, ic ); // normals
 
-					}
+				if ( na !== undefined && na !== '' ) {
 
-				},
-				addLineGeometry: function ( vertices, uvs ) {
+					const nLen = this.normals.length;
+					ia = this.parseNormalIndex( na, nLen );
+					ib = this.parseNormalIndex( nb, nLen );
+					ic = this.parseNormalIndex( nc, nLen );
+					this.addNormal( ia, ib, ic );
 
-					this.object.geometry.type = 'Line';
-					var vLen = this.vertices.length;
-					var uvLen = this.uvs.length;
+				} else {
 
-					for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) {
+					this.addFaceNormal( ia, ib, ic );
 
-						this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) );
+				} // uvs
 
-					}
 
-					for ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) {
+				if ( ua !== undefined && ua !== '' ) {
 
-						this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) );
+					const uvLen = this.uvs.length;
+					ia = this.parseUVIndex( ua, uvLen );
+					ib = this.parseUVIndex( ub, uvLen );
+					ic = this.parseUVIndex( uc, uvLen );
+					this.addUV( ia, ib, ic );
+					this.object.geometry.hasUVIndices = true;
 
-					}
+				} else {
+
+					// add placeholder values (for inconsistent face definitions)
+					this.addDefaultUV();
 
 				}
-			};
-			state.startObject( '', false );
-			return state;
 
-		} //
+			},
+			addPointGeometry: function ( vertices ) {
 
+				this.object.geometry.type = 'Points';
+				const vLen = this.vertices.length;
 
-		function OBJLoader( manager ) {
+				for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) {
 
-			THREE.Loader.call( this, manager );
-			this.materials = null;
+					const index = this.parseVertexIndex( vertices[ vi ], vLen );
+					this.addVertexPoint( index );
+					this.addColor( index );
 
-		}
+				}
 
-		OBJLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {
-			constructor: OBJLoader,
-			load: function ( url, onLoad, onProgress, onError ) {
+			},
+			addLineGeometry: function ( vertices, uvs ) {
 
-				var scope = this;
-				var loader = new THREE.FileLoader( this.manager );
-				loader.setPath( this.path );
-				loader.setRequestHeader( this.requestHeader );
-				loader.setWithCredentials( this.withCredentials );
-				loader.load( url, function ( text ) {
+				this.object.geometry.type = 'Line';
+				const vLen = this.vertices.length;
+				const uvLen = this.uvs.length;
 
-					try {
+				for ( let vi = 0, l = vertices.length; vi < l; vi ++ ) {
 
-						onLoad( scope.parse( text ) );
+					this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) );
 
-					} catch ( e ) {
+				}
 
-						if ( onError ) {
+				for ( let uvi = 0, l = uvs.length; uvi < l; uvi ++ ) {
 
-							onError( e );
+					this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) );
 
-						} else {
+				}
 
-							console.error( e );
+			}
+		};
+		state.startObject( '', false );
+		return state;
 
-						}
+	} //
 
-						scope.manager.itemError( url );
 
-					}
+	class OBJLoader extends THREE.Loader {
 
-				}, onProgress, onError );
+		constructor( manager ) {
 
-			},
-			setMaterials: function ( materials ) {
+			super( manager );
+			this.materials = null;
 
-				this.materials = materials;
-				return this;
+		}
 
-			},
-			parse: function ( text ) {
+		load( url, onLoad, onProgress, onError ) {
 
-				var state = new ParserState();
+			const scope = this;
+			const loader = new THREE.FileLoader( this.manager );
+			loader.setPath( this.path );
+			loader.setRequestHeader( this.requestHeader );
+			loader.setWithCredentials( this.withCredentials );
+			loader.load( url, function ( text ) {
 
-				if ( text.indexOf( '\r\n' ) !== - 1 ) {
+				try {
 
-					// This is faster than String.split with regex that splits on both
-					text = text.replace( /\r\n/g, '\n' );
+					onLoad( scope.parse( text ) );
 
-				}
+				} catch ( e ) {
+
+					if ( onError ) {
 
-				if ( text.indexOf( '\\\n' ) !== - 1 ) {
+						onError( e );
+
+					} else {
 
-					// join lines separated by a line continuation character (\)
-					text = text.replace( /\\\n/g, '' );
+						console.error( e );
+
+					}
+
+					scope.manager.itemError( url );
 
 				}
 
-				var lines = text.split( '\n' );
-				var line = '',
-					lineFirstChar = '';
-				var lineLength = 0;
-				var result = []; // Faster to just trim left side of the line. Use if available.
+			}, onProgress, onError );
 
-				var trimLeft = typeof ''.trimLeft === 'function';
+		}
 
-				for ( var i = 0, l = lines.length; i < l; i ++ ) {
+		setMaterials( materials ) {
 
-					line = lines[ i ];
-					line = trimLeft ? line.trimLeft() : line.trim();
-					lineLength = line.length;
-					if ( lineLength === 0 ) continue;
-					lineFirstChar = line.charAt( 0 ); // @todo invoke passed in handler if any
+			this.materials = materials;
+			return this;
 
-					if ( lineFirstChar === '#' ) continue;
+		}
 
-					if ( lineFirstChar === 'v' ) {
+		parse( text ) {
 
-						var data = line.split( /\s+/ );
+			const state = new ParserState();
 
-						switch ( data[ 0 ] ) {
+			if ( text.indexOf( '\r\n' ) !== - 1 ) {
 
-							case 'v':
-								state.vertices.push( parseFloat( data[ 1 ] ), parseFloat( data[ 2 ] ), parseFloat( data[ 3 ] ) );
+				// This is faster than String.split with regex that splits on both
+				text = text.replace( /\r\n/g, '\n' );
 
-								if ( data.length >= 7 ) {
+			}
 
-									state.colors.push( parseFloat( data[ 4 ] ), parseFloat( data[ 5 ] ), parseFloat( data[ 6 ] ) );
+			if ( text.indexOf( '\\\n' ) !== - 1 ) {
 
-								} else {
+				// join lines separated by a line continuation character (\)
+				text = text.replace( /\\\n/g, '' );
 
-									// if no colors are defined, add placeholders so color and vertex indices match
-									state.colors.push( undefined, undefined, undefined );
+			}
 
-								}
+			const lines = text.split( '\n' );
+			let line = '',
+				lineFirstChar = '';
+			let lineLength = 0;
+			let result = []; // Faster to just trim left side of the line. Use if available.
 
-								break;
+			const trimLeft = typeof ''.trimLeft === 'function';
 
-							case 'vn':
-								state.normals.push( parseFloat( data[ 1 ] ), parseFloat( data[ 2 ] ), parseFloat( data[ 3 ] ) );
-								break;
+			for ( let i = 0, l = lines.length; i < l; i ++ ) {
 
-							case 'vt':
-								state.uvs.push( parseFloat( data[ 1 ] ), parseFloat( data[ 2 ] ) );
-								break;
+				line = lines[ i ];
+				line = trimLeft ? line.trimLeft() : line.trim();
+				lineLength = line.length;
+				if ( lineLength === 0 ) continue;
+				lineFirstChar = line.charAt( 0 ); // @todo invoke passed in handler if any
 
-						}
+				if ( lineFirstChar === '#' ) continue;
+
+				if ( lineFirstChar === 'v' ) {
 
-					} else if ( lineFirstChar === 'f' ) {
+					const data = line.split( /\s+/ );
 
-						var lineData = line.substr( 1 ).trim();
-						var vertexData = lineData.split( /\s+/ );
-						var faceVertices = []; // Parse the face vertex data into an easy to work with format
+					switch ( data[ 0 ] ) {
 
-						for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) {
+						case 'v':
+							state.vertices.push( parseFloat( data[ 1 ] ), parseFloat( data[ 2 ] ), parseFloat( data[ 3 ] ) );
 
-							var vertex = vertexData[ j ];
+							if ( data.length >= 7 ) {
 
-							if ( vertex.length > 0 ) {
+								state.colors.push( parseFloat( data[ 4 ] ), parseFloat( data[ 5 ] ), parseFloat( data[ 6 ] ) );
 
-								var vertexParts = vertex.split( '/' );
-								faceVertices.push( vertexParts );
+							} else {
+
+								// if no colors are defined, add placeholders so color and vertex indices match
+								state.colors.push( undefined, undefined, undefined );
 
 							}
 
-						} // Draw an edge between the first vertex and all subsequent vertices to form an n-gon
+							break;
+
+						case 'vn':
+							state.normals.push( parseFloat( data[ 1 ] ), parseFloat( data[ 2 ] ), parseFloat( data[ 3 ] ) );
+							break;
+
+						case 'vt':
+							state.uvs.push( parseFloat( data[ 1 ] ), parseFloat( data[ 2 ] ) );
+							break;
+
+					}
+
+				} else if ( lineFirstChar === 'f' ) {
 
+					const lineData = line.substr( 1 ).trim();
+					const vertexData = lineData.split( /\s+/ );
+					const faceVertices = []; // Parse the face vertex data into an easy to work with format
 
-						var v1 = faceVertices[ 0 ];
+					for ( let j = 0, jl = vertexData.length; j < jl; j ++ ) {
 
-						for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) {
+						const vertex = vertexData[ j ];
 
-							var v2 = faceVertices[ j ];
-							var v3 = faceVertices[ j + 1 ];
-							state.addFace( v1[ 0 ], v2[ 0 ], v3[ 0 ], v1[ 1 ], v2[ 1 ], v3[ 1 ], v1[ 2 ], v2[ 2 ], v3[ 2 ] );
+						if ( vertex.length > 0 ) {
+
+							const vertexParts = vertex.split( '/' );
+							faceVertices.push( vertexParts );
 
 						}
 
-					} else if ( lineFirstChar === 'l' ) {
+					} // Draw an edge between the first vertex and all subsequent vertices to form an n-gon
 
-						var lineParts = line.substring( 1 ).trim().split( ' ' );
-						var lineVertices = [],
-							lineUVs = [];
 
-						if ( line.indexOf( '/' ) === - 1 ) {
+					const v1 = faceVertices[ 0 ];
 
-							lineVertices = lineParts;
+					for ( let j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) {
 
-						} else {
+						const v2 = faceVertices[ j ];
+						const v3 = faceVertices[ j + 1 ];
+						state.addFace( v1[ 0 ], v2[ 0 ], v3[ 0 ], v1[ 1 ], v2[ 1 ], v3[ 1 ], v1[ 2 ], v2[ 2 ], v3[ 2 ] );
 
-							for ( var li = 0, llen = lineParts.length; li < llen; li ++ ) {
+					}
 
-								var parts = lineParts[ li ].split( '/' );
-								if ( parts[ 0 ] !== '' ) lineVertices.push( parts[ 0 ] );
-								if ( parts[ 1 ] !== '' ) lineUVs.push( parts[ 1 ] );
+				} else if ( lineFirstChar === 'l' ) {
 
-							}
+					const lineParts = line.substring( 1 ).trim().split( ' ' );
+					let lineVertices = [];
+					const lineUVs = [];
+
+					if ( line.indexOf( '/' ) === - 1 ) {
+
+						lineVertices = lineParts;
+
+					} else {
+
+						for ( let li = 0, llen = lineParts.length; li < llen; li ++ ) {
+
+							const parts = lineParts[ li ].split( '/' );
+							if ( parts[ 0 ] !== '' ) lineVertices.push( parts[ 0 ] );
+							if ( parts[ 1 ] !== '' ) lineUVs.push( parts[ 1 ] );
 
 						}
 
-						state.addLineGeometry( lineVertices, lineUVs );
+					}
+
+					state.addLineGeometry( lineVertices, lineUVs );
 
-					} else if ( lineFirstChar === 'p' ) {
+				} else if ( lineFirstChar === 'p' ) {
 
-						var lineData = line.substr( 1 ).trim();
-						var pointData = lineData.split( ' ' );
-						state.addPointGeometry( pointData );
+					const lineData = line.substr( 1 ).trim();
+					const pointData = lineData.split( ' ' );
+					state.addPointGeometry( pointData );
 
-					} else if ( ( result = object_pattern.exec( line ) ) !== null ) {
+				} else if ( ( result = _object_pattern.exec( line ) ) !== null ) {
 
-						// o object_name
-						// or
-						// g group_name
-						// WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869
-						// var name = result[ 0 ].substr( 1 ).trim();
-						var name = ( ' ' + result[ 0 ].substr( 1 ).trim() ).substr( 1 );
-						state.startObject( name );
+					// o object_name
+					// or
+					// g group_name
+					// WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869
+					// let name = result[ 0 ].substr( 1 ).trim();
+					const name = ( ' ' + result[ 0 ].substr( 1 ).trim() ).substr( 1 );
+					state.startObject( name );
 
-					} else if ( material_use_pattern.test( line ) ) {
+				} else if ( _material_use_pattern.test( line ) ) {
 
-						// material
-						state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries );
+					// material
+					state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries );
 
-					} else if ( material_library_pattern.test( line ) ) {
+				} else if ( _material_library_pattern.test( line ) ) {
 
-						// mtl file
-						state.materialLibraries.push( line.substring( 7 ).trim() );
+					// mtl file
+					state.materialLibraries.push( line.substring( 7 ).trim() );
 
-					} else if ( map_use_pattern.test( line ) ) {
+				} else if ( _map_use_pattern.test( line ) ) {
 
-						// the line is parsed but ignored since the loader assumes textures are defined MTL files
-						// (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method)
-						console.warn( 'THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.' );
+					// the line is parsed but ignored since the loader assumes textures are defined MTL files
+					// (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method)
+					console.warn( 'THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.' );
 
-					} else if ( lineFirstChar === 's' ) {
+				} else if ( lineFirstChar === 's' ) {
 
-						result = line.split( ' ' ); // smooth shading
-						// @todo Handle files that have varying smooth values for a set of faces inside one geometry,
-						// but does not define a usemtl for each face set.
-						// This should be detected and a dummy material created (later MultiMaterial and geometry groups).
-						// This requires some care to not create extra material on each smooth value for "normal" obj files.
-						// where explicit usemtl defines geometry groups.
-						// Example asset: examples/models/obj/cerberus/Cerberus.obj
+					result = line.split( ' ' ); // smooth shading
+					// @todo Handle files that have varying smooth values for a set of faces inside one geometry,
+					// but does not define a usemtl for each face set.
+					// This should be detected and a dummy material created (later MultiMaterial and geometry groups).
+					// This requires some care to not create extra material on each smooth value for "normal" obj files.
+					// where explicit usemtl defines geometry groups.
+					// Example asset: examples/models/obj/cerberus/Cerberus.obj
 
-						/*
+					/*
 					 * http://paulbourke.net/dataformats/obj/
 					 * or
 					 * http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf
@@ -581,217 +593,215 @@
 					 * than 0."
 					 */
 
-						if ( result.length > 1 ) {
+					if ( result.length > 1 ) {
 
-							var value = result[ 1 ].trim().toLowerCase();
-							state.object.smooth = value !== '0' && value !== 'off';
-
-						} else {
+						const value = result[ 1 ].trim().toLowerCase();
+						state.object.smooth = value !== '0' && value !== 'off';
 
-							// ZBrush can produce "s" lines #11707
-							state.object.smooth = true;
+					} else {
 
-						}
+						// ZBrush can produce "s" lines #11707
+						state.object.smooth = true;
 
-						var material = state.object.currentMaterial();
-						if ( material ) material.smooth = state.object.smooth;
+					}
 
-					} else {
+					const material = state.object.currentMaterial();
+					if ( material ) material.smooth = state.object.smooth;
 
-						// Handle null terminated files without exception
-						if ( line === '\0' ) continue;
-						console.warn( 'THREE.OBJLoader: Unexpected line: "' + line + '"' );
+				} else {
 
-					}
+					// Handle null terminated files without exception
+					if ( line === '\0' ) continue;
+					console.warn( 'THREE.OBJLoader: Unexpected line: "' + line + '"' );
 
 				}
 
-				state.finalize();
-				var container = new THREE.Group();
-				container.materialLibraries = [].concat( state.materialLibraries );
-				var hasPrimitives = ! ( state.objects.length === 1 && state.objects[ 0 ].geometry.vertices.length === 0 );
+			}
 
-				if ( hasPrimitives === true ) {
+			state.finalize();
+			const container = new THREE.Group();
+			container.materialLibraries = [].concat( state.materialLibraries );
+			const hasPrimitives = ! ( state.objects.length === 1 && state.objects[ 0 ].geometry.vertices.length === 0 );
 
-					for ( var i = 0, l = state.objects.length; i < l; i ++ ) {
+			if ( hasPrimitives === true ) {
 
-						var object = state.objects[ i ];
-						var geometry = object.geometry;
-						var materials = object.materials;
-						var isLine = geometry.type === 'Line';
-						var isPoints = geometry.type === 'Points';
-						var hasVertexColors = false; // Skip o/g line declarations that did not follow with any faces
+				for ( let i = 0, l = state.objects.length; i < l; i ++ ) {
 
-						if ( geometry.vertices.length === 0 ) continue;
-						var buffergeometry = new THREE.BufferGeometry();
-						buffergeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( geometry.vertices, 3 ) );
+					const object = state.objects[ i ];
+					const geometry = object.geometry;
+					const materials = object.materials;
+					const isLine = geometry.type === 'Line';
+					const isPoints = geometry.type === 'Points';
+					let hasVertexColors = false; // Skip o/g line declarations that did not follow with any faces
 
-						if ( geometry.normals.length > 0 ) {
+					if ( geometry.vertices.length === 0 ) continue;
+					const buffergeometry = new THREE.BufferGeometry();
+					buffergeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( geometry.vertices, 3 ) );
 
-							buffergeometry.setAttribute( 'normal', new THREE.Float32BufferAttribute( geometry.normals, 3 ) );
+					if ( geometry.normals.length > 0 ) {
 
-						}
+						buffergeometry.setAttribute( 'normal', new THREE.Float32BufferAttribute( geometry.normals, 3 ) );
 
-						if ( geometry.colors.length > 0 ) {
+					}
 
-							hasVertexColors = true;
-							buffergeometry.setAttribute( 'color', new THREE.Float32BufferAttribute( geometry.colors, 3 ) );
+					if ( geometry.colors.length > 0 ) {
 
-						}
+						hasVertexColors = true;
+						buffergeometry.setAttribute( 'color', new THREE.Float32BufferAttribute( geometry.colors, 3 ) );
 
-						if ( geometry.hasUVIndices === true ) {
+					}
 
-							buffergeometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( geometry.uvs, 2 ) );
+					if ( geometry.hasUVIndices === true ) {
 
-						} // Create materials
+						buffergeometry.setAttribute( 'uv', new THREE.Float32BufferAttribute( geometry.uvs, 2 ) );
 
+					} // Create materials
 
-						var createdMaterials = [];
 
-						for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {
+					const createdMaterials = [];
 
-							var sourceMaterial = materials[ mi ];
-							var materialHash = sourceMaterial.name + '_' + sourceMaterial.smooth + '_' + hasVertexColors;
-							var material = state.materials[ materialHash ];
+					for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {
 
-							if ( this.materials !== null ) {
+						const sourceMaterial = materials[ mi ];
+						const materialHash = sourceMaterial.name + '_' + sourceMaterial.smooth + '_' + hasVertexColors;
+						let material = state.materials[ materialHash ];
 
-								material = this.materials.create( sourceMaterial.name ); // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.
+						if ( this.materials !== null ) {
 
-								if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) {
+							material = this.materials.create( sourceMaterial.name ); // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.
 
-									var materialLine = new THREE.LineBasicMaterial();
-									THREE.Material.prototype.copy.call( materialLine, material );
-									materialLine.color.copy( material.color );
-									material = materialLine;
+							if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) {
 
-								} else if ( isPoints && material && ! ( material instanceof THREE.PointsMaterial ) ) {
+								const materialLine = new THREE.LineBasicMaterial();
+								THREE.Material.prototype.copy.call( materialLine, material );
+								materialLine.color.copy( material.color );
+								material = materialLine;
 
-									var materialPoints = new THREE.PointsMaterial( {
-										size: 10,
-										sizeAttenuation: false
-									} );
-									THREE.Material.prototype.copy.call( materialPoints, material );
-									materialPoints.color.copy( material.color );
-									materialPoints.map = material.map;
-									material = materialPoints;
+							} else if ( isPoints && material && ! ( material instanceof THREE.PointsMaterial ) ) {
 
-								}
+								const materialPoints = new THREE.PointsMaterial( {
+									size: 10,
+									sizeAttenuation: false
+								} );
+								THREE.Material.prototype.copy.call( materialPoints, material );
+								materialPoints.color.copy( material.color );
+								materialPoints.map = material.map;
+								material = materialPoints;
 
 							}
 
-							if ( material === undefined ) {
-
-								if ( isLine ) {
+						}
 
-									material = new THREE.LineBasicMaterial();
+						if ( material === undefined ) {
 
-								} else if ( isPoints ) {
+							if ( isLine ) {
 
-									material = new THREE.PointsMaterial( {
-										size: 1,
-										sizeAttenuation: false
-									} );
+								material = new THREE.LineBasicMaterial();
 
-								} else {
+							} else if ( isPoints ) {
 
-									material = new THREE.MeshPhongMaterial();
+								material = new THREE.PointsMaterial( {
+									size: 1,
+									sizeAttenuation: false
+								} );
 
-								}
+							} else {
 
-								material.name = sourceMaterial.name;
-								material.flatShading = sourceMaterial.smooth ? false : true;
-								material.vertexColors = hasVertexColors;
-								state.materials[ materialHash ] = material;
+								material = new THREE.MeshPhongMaterial();
 
 							}
 
-							createdMaterials.push( material );
-
-						} // Create mesh
+							material.name = sourceMaterial.name;
+							material.flatShading = sourceMaterial.smooth ? false : true;
+							material.vertexColors = hasVertexColors;
+							state.materials[ materialHash ] = material;
 
+						}
 
-						var mesh;
+						createdMaterials.push( material );
 
-						if ( createdMaterials.length > 1 ) {
+					} // Create mesh
 
-							for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {
 
-								var sourceMaterial = materials[ mi ];
-								buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi );
+					let mesh;
 
-							}
+					if ( createdMaterials.length > 1 ) {
 
-							if ( isLine ) {
+						for ( let mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {
 
-								mesh = new THREE.LineSegments( buffergeometry, createdMaterials );
+							const sourceMaterial = materials[ mi ];
+							buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi );
 
-							} else if ( isPoints ) {
+						}
 
-								mesh = new THREE.Points( buffergeometry, createdMaterials );
+						if ( isLine ) {
 
-							} else {
+							mesh = new THREE.LineSegments( buffergeometry, createdMaterials );
 
-								mesh = new THREE.Mesh( buffergeometry, createdMaterials );
+						} else if ( isPoints ) {
 
-							}
+							mesh = new THREE.Points( buffergeometry, createdMaterials );
 
 						} else {
 
-							if ( isLine ) {
+							mesh = new THREE.Mesh( buffergeometry, createdMaterials );
 
-								mesh = new THREE.LineSegments( buffergeometry, createdMaterials[ 0 ] );
+						}
 
-							} else if ( isPoints ) {
+					} else {
 
-								mesh = new THREE.Points( buffergeometry, createdMaterials[ 0 ] );
+						if ( isLine ) {
 
-							} else {
+							mesh = new THREE.LineSegments( buffergeometry, createdMaterials[ 0 ] );
 
-								mesh = new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] );
+						} else if ( isPoints ) {
 
-							}
+							mesh = new THREE.Points( buffergeometry, createdMaterials[ 0 ] );
 
-						}
+						} else {
 
-						mesh.name = object.name;
-						container.add( mesh );
+							mesh = new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] );
+
+						}
 
 					}
 
-				} else {
+					mesh.name = object.name;
+					container.add( mesh );
 
-					// if there is only the default parser state object with no geometry data, interpret data as point cloud
-					if ( state.vertices.length > 0 ) {
+				}
 
-						var material = new THREE.PointsMaterial( {
-							size: 1,
-							sizeAttenuation: false
-						} );
-						var buffergeometry = new THREE.BufferGeometry();
-						buffergeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( state.vertices, 3 ) );
+			} else {
 
-						if ( state.colors.length > 0 && state.colors[ 0 ] !== undefined ) {
+				// if there is only the default parser state object with no geometry data, interpret data as point cloud
+				if ( state.vertices.length > 0 ) {
 
-							buffergeometry.setAttribute( 'color', new THREE.Float32BufferAttribute( state.colors, 3 ) );
-							material.vertexColors = true;
+					const material = new THREE.PointsMaterial( {
+						size: 1,
+						sizeAttenuation: false
+					} );
+					const buffergeometry = new THREE.BufferGeometry();
+					buffergeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( state.vertices, 3 ) );
 
-						}
+					if ( state.colors.length > 0 && state.colors[ 0 ] !== undefined ) {
 
-						var points = new THREE.Points( buffergeometry, material );
-						container.add( points );
+						buffergeometry.setAttribute( 'color', new THREE.Float32BufferAttribute( state.colors, 3 ) );
+						material.vertexColors = true;
 
 					}
 
-				}
+					const points = new THREE.Points( buffergeometry, material );
+					container.add( points );
 
-				return container;
+				}
 
 			}
-		} );
-		return OBJLoader;
 
-	}();
+			return container;
+
+		}
+
+	}
 
 	THREE.OBJLoader = OBJLoader;
 

+ 147 - 163
examples/js/loaders/PRWMLoader.js

@@ -4,272 +4,256 @@
  * See https://github.com/kchapelier/PRWM for more informations about this file format
  */
 
-	var PRWMLoader = function () {
-
-		var bigEndianPlatform = null;
-		/**
+	let bigEndianPlatform = null;
+	/**
 	 * Check if the endianness of the platform is big-endian (most significant bit first)
 	 * @returns {boolean} True if big-endian, false if little-endian
 	 */
 
-		function isBigEndianPlatform() {
+	function isBigEndianPlatform() {
 
-			if ( bigEndianPlatform === null ) {
+		if ( bigEndianPlatform === null ) {
 
-				var buffer = new ArrayBuffer( 2 ),
-					uint8Array = new Uint8Array( buffer ),
-					uint16Array = new Uint16Array( buffer );
-				uint8Array[ 0 ] = 0xAA; // set first byte
+			const buffer = new ArrayBuffer( 2 ),
+				uint8Array = new Uint8Array( buffer ),
+				uint16Array = new Uint16Array( buffer );
+			uint8Array[ 0 ] = 0xAA; // set first byte
 
-				uint8Array[ 1 ] = 0xBB; // set second byte
+			uint8Array[ 1 ] = 0xBB; // set second byte
 
-				bigEndianPlatform = uint16Array[ 0 ] === 0xAABB;
+			bigEndianPlatform = uint16Array[ 0 ] === 0xAABB;
 
-			}
+		}
 
-			return bigEndianPlatform;
+		return bigEndianPlatform;
 
-		} // match the values defined in the spec to the TypedArray types
+	} // match the values defined in the spec to the TypedArray types
 
 
-		var InvertedEncodingTypes = [ null, Float32Array, null, Int8Array, Int16Array, null, Int32Array, Uint8Array, Uint16Array, null, Uint32Array ]; // define the method to use on a DataView, corresponding the TypedArray type
+	const InvertedEncodingTypes = [ null, Float32Array, null, Int8Array, Int16Array, null, Int32Array, Uint8Array, Uint16Array, null, Uint32Array ]; // define the method to use on a DataView, corresponding the TypedArray type
 
-		var getMethods = {
-			Uint16Array: 'getUint16',
-			Uint32Array: 'getUint32',
-			Int16Array: 'getInt16',
-			Int32Array: 'getInt32',
-			Float32Array: 'getFloat32',
-			Float64Array: 'getFloat64'
-		};
+	const getMethods = {
+		Uint16Array: 'getUint16',
+		Uint32Array: 'getUint32',
+		Int16Array: 'getInt16',
+		Int32Array: 'getInt32',
+		Float32Array: 'getFloat32',
+		Float64Array: 'getFloat64'
+	};
 
-		function copyFromBuffer( sourceArrayBuffer, viewType, position, length, fromBigEndian ) {
+	function copyFromBuffer( sourceArrayBuffer, viewType, position, length, fromBigEndian ) {
 
-			var bytesPerElement = viewType.BYTES_PER_ELEMENT,
-				result;
+		const bytesPerElement = viewType.BYTES_PER_ELEMENT;
+		let result;
 
-			if ( fromBigEndian === isBigEndianPlatform() || bytesPerElement === 1 ) {
+		if ( fromBigEndian === isBigEndianPlatform() || bytesPerElement === 1 ) {
 
-				result = new viewType( sourceArrayBuffer, position, length );
+			result = new viewType( sourceArrayBuffer, position, length );
 
-			} else {
+		} else {
 
-				var readView = new DataView( sourceArrayBuffer, position, length * bytesPerElement ),
-					getMethod = getMethods[ viewType.name ],
-					littleEndian = ! fromBigEndian,
-					i = 0;
-				result = new viewType( length );
+			const readView = new DataView( sourceArrayBuffer, position, length * bytesPerElement ),
+				getMethod = getMethods[ viewType.name ],
+				littleEndian = ! fromBigEndian;
+			result = new viewType( length );
 
-				for ( ; i < length; i ++ ) {
+			for ( let i = 0; i < length; i ++ ) {
 
-					result[ i ] = readView[ getMethod ]( i * bytesPerElement, littleEndian );
-
-				}
+				result[ i ] = readView[ getMethod ]( i * bytesPerElement, littleEndian );
 
 			}
 
-			return result;
-
 		}
 
-		function decodePrwm( buffer ) {
+		return result;
 
-			var array = new Uint8Array( buffer ),
-				version = array[ 0 ],
-				flags = array[ 1 ],
-				indexedGeometry = !! ( flags >> 7 & 0x01 ),
-				indicesType = flags >> 6 & 0x01,
-				bigEndian = ( flags >> 5 & 0x01 ) === 1,
-				attributesNumber = flags & 0x1F,
-				valuesNumber = 0,
-				indicesNumber = 0;
+	}
 
-			if ( bigEndian ) {
+	function decodePrwm( buffer ) {
 
-				valuesNumber = ( array[ 2 ] << 16 ) + ( array[ 3 ] << 8 ) + array[ 4 ];
-				indicesNumber = ( array[ 5 ] << 16 ) + ( array[ 6 ] << 8 ) + array[ 7 ];
+		const array = new Uint8Array( buffer ),
+			version = array[ 0 ];
+		let flags = array[ 1 ];
+		const indexedGeometry = !! ( flags >> 7 & 0x01 ),
+			indicesType = flags >> 6 & 0x01,
+			bigEndian = ( flags >> 5 & 0x01 ) === 1,
+			attributesNumber = flags & 0x1F;
+		let valuesNumber = 0,
+			indicesNumber = 0;
 
-			} else {
+		if ( bigEndian ) {
 
-				valuesNumber = array[ 2 ] + ( array[ 3 ] << 8 ) + ( array[ 4 ] << 16 );
-				indicesNumber = array[ 5 ] + ( array[ 6 ] << 8 ) + ( array[ 7 ] << 16 );
+			valuesNumber = ( array[ 2 ] << 16 ) + ( array[ 3 ] << 8 ) + array[ 4 ];
+			indicesNumber = ( array[ 5 ] << 16 ) + ( array[ 6 ] << 8 ) + array[ 7 ];
 
-			}
-			/** PRELIMINARY CHECKS **/
+		} else {
 
+			valuesNumber = array[ 2 ] + ( array[ 3 ] << 8 ) + ( array[ 4 ] << 16 );
+			indicesNumber = array[ 5 ] + ( array[ 6 ] << 8 ) + ( array[ 7 ] << 16 );
 
-			if ( version === 0 ) {
+		}
+		/** PRELIMINARY CHECKS **/
 
-				throw new Error( 'PRWM decoder: Invalid format version: 0' );
 
-			} else if ( version !== 1 ) {
+		if ( version === 0 ) {
 
-				throw new Error( 'PRWM decoder: Unsupported format version: ' + version );
+			throw new Error( 'PRWM decoder: Invalid format version: 0' );
 
-			}
+		} else if ( version !== 1 ) {
 
-			if ( ! indexedGeometry ) {
+			throw new Error( 'PRWM decoder: Unsupported format version: ' + version );
 
-				if ( indicesType !== 0 ) {
+		}
 
-					throw new Error( 'PRWM decoder: Indices type must be set to 0 for non-indexed geometries' );
+		if ( ! indexedGeometry ) {
 
-				} else if ( indicesNumber !== 0 ) {
+			if ( indicesType !== 0 ) {
 
-					throw new Error( 'PRWM decoder: Number of indices must be set to 0 for non-indexed geometries' );
+				throw new Error( 'PRWM decoder: Indices type must be set to 0 for non-indexed geometries' );
 
-				}
+			} else if ( indicesNumber !== 0 ) {
+
+				throw new Error( 'PRWM decoder: Number of indices must be set to 0 for non-indexed geometries' );
 
 			}
-			/** PARSING **/
 
+		}
+		/** PARSING **/
 
-			var pos = 8;
-			var attributes = {},
-				attributeName,
-				char,
-				attributeType,
-				cardinality,
-				encodingType,
-				arrayType,
-				values,
-				indices,
-				i;
 
-			for ( i = 0; i < attributesNumber; i ++ ) {
+		let pos = 8;
+		const attributes = {};
 
-				attributeName = '';
+		for ( let i = 0; i < attributesNumber; i ++ ) {
 
-				while ( pos < array.length ) {
+			let attributeName = '';
 
-					char = array[ pos ];
-					pos ++;
+			while ( pos < array.length ) {
 
-					if ( char === 0 ) {
+				const char = array[ pos ];
+				pos ++;
 
-						break;
+				if ( char === 0 ) {
 
-					} else {
+					break;
 
-						attributeName += String.fromCharCode( char );
+				} else {
 
-					}
+					attributeName += String.fromCharCode( char );
 
 				}
 
-				flags = array[ pos ];
-				attributeType = flags >> 7 & 0x01;
-				cardinality = ( flags >> 4 & 0x03 ) + 1;
-				encodingType = flags & 0x0F;
-				arrayType = InvertedEncodingTypes[ encodingType ];
-				pos ++; // padding to next multiple of 4
-
-				pos = Math.ceil( pos / 4 ) * 4;
-				values = copyFromBuffer( buffer, arrayType, pos, cardinality * valuesNumber, bigEndian );
-				pos += arrayType.BYTES_PER_ELEMENT * cardinality * valuesNumber;
-				attributes[ attributeName ] = {
-					type: attributeType,
-					cardinality: cardinality,
-					values: values
-				};
-
 			}
 
+			flags = array[ pos ];
+			const attributeType = flags >> 7 & 0x01;
+			const cardinality = ( flags >> 4 & 0x03 ) + 1;
+			const encodingType = flags & 0x0F;
+			const arrayType = InvertedEncodingTypes[ encodingType ];
+			pos ++; // padding to next multiple of 4
+
 			pos = Math.ceil( pos / 4 ) * 4;
-			indices = null;
+			const values = copyFromBuffer( buffer, arrayType, pos, cardinality * valuesNumber, bigEndian );
+			pos += arrayType.BYTES_PER_ELEMENT * cardinality * valuesNumber;
+			attributes[ attributeName ] = {
+				type: attributeType,
+				cardinality: cardinality,
+				values: values
+			};
 
-			if ( indexedGeometry ) {
+		}
 
-				indices = copyFromBuffer( buffer, indicesType === 1 ? Uint32Array : Uint16Array, pos, indicesNumber, bigEndian );
+		pos = Math.ceil( pos / 4 ) * 4;
+		let indices = null;
 
-			}
+		if ( indexedGeometry ) {
 
-			return {
-				version: version,
-				attributes: attributes,
-				indices: indices
-			};
+			indices = copyFromBuffer( buffer, indicesType === 1 ? Uint32Array : Uint16Array, pos, indicesNumber, bigEndian );
 
-		} // Define the public interface
+		}
 
+		return {
+			version: version,
+			attributes: attributes,
+			indices: indices
+		};
 
-		function PRWMLoader( manager ) {
+	} // Define the public interface
 
-			THREE.Loader.call( this, manager );
 
-		}
+	class PRWMLoader extends THREE.Loader {
 
-		PRWMLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {
-			constructor: PRWMLoader,
-			load: function ( url, onLoad, onProgress, onError ) {
+		constructor( manager ) {
 
-				var scope = this;
-				var loader = new THREE.FileLoader( scope.manager );
-				loader.setPath( scope.path );
-				loader.setResponseType( 'arraybuffer' );
-				loader.setRequestHeader( scope.requestHeader );
-				loader.setWithCredentials( scope.withCredentials );
-				url = url.replace( /\*/g, isBigEndianPlatform() ? 'be' : 'le' );
-				loader.load( url, function ( arrayBuffer ) {
+			super( manager );
 
-					try {
+		}
+
+		load( url, onLoad, onProgress, onError ) {
 
-						onLoad( scope.parse( arrayBuffer ) );
+			const scope = this;
+			const loader = new THREE.FileLoader( scope.manager );
+			loader.setPath( scope.path );
+			loader.setResponseType( 'arraybuffer' );
+			loader.setRequestHeader( scope.requestHeader );
+			loader.setWithCredentials( scope.withCredentials );
+			url = url.replace( /\*/g, isBigEndianPlatform() ? 'be' : 'le' );
+			loader.load( url, function ( arrayBuffer ) {
 
-					} catch ( e ) {
+				try {
 
-						if ( onError ) {
+					onLoad( scope.parse( arrayBuffer ) );
 
-							onError( e );
+				} catch ( e ) {
 
-						} else {
+					if ( onError ) {
 
-							console.error( e );
+						onError( e );
 
-						}
+					} else {
 
-						scope.manager.itemError( url );
+						console.error( e );
 
 					}
 
-				}, onProgress, onError );
+					scope.manager.itemError( url );
+
+				}
 
-			},
-			parse: function ( arrayBuffer ) {
+			}, onProgress, onError );
 
-				var data = decodePrwm( arrayBuffer ),
-					attributesKey = Object.keys( data.attributes ),
-					bufferGeometry = new THREE.BufferGeometry(),
-					attribute,
-					i;
+		}
 
-				for ( i = 0; i < attributesKey.length; i ++ ) {
+		parse( arrayBuffer ) {
 
-					attribute = data.attributes[ attributesKey[ i ] ];
-					bufferGeometry.setAttribute( attributesKey[ i ], new THREE.BufferAttribute( attribute.values, attribute.cardinality, attribute.normalized ) );
+			const data = decodePrwm( arrayBuffer ),
+				attributesKey = Object.keys( data.attributes ),
+				bufferGeometry = new THREE.BufferGeometry();
 
-				}
+			for ( let i = 0; i < attributesKey.length; i ++ ) {
 
-				if ( data.indices !== null ) {
+				const attribute = data.attributes[ attributesKey[ i ] ];
+				bufferGeometry.setAttribute( attributesKey[ i ], new THREE.BufferAttribute( attribute.values, attribute.cardinality, attribute.normalized ) );
 
-					bufferGeometry.setIndex( new THREE.BufferAttribute( data.indices, 1 ) );
+			}
 
-				}
+			if ( data.indices !== null ) {
 
-				return bufferGeometry;
+				bufferGeometry.setIndex( new THREE.BufferAttribute( data.indices, 1 ) );
 
 			}
-		} );
 
-		PRWMLoader.isBigEndianPlatform = function () {
+			return bufferGeometry;
 
-			return isBigEndianPlatform();
+		}
 
-		};
+		static isBigEndianPlatform() {
 
-		return PRWMLoader;
+			return isBigEndianPlatform();
+
+		}
 
-	}();
+	}
 
 	THREE.PRWMLoader = PRWMLoader;
 

文件差異過大導致無法顯示
+ 528 - 546
examples/js/loaders/SVGLoader.js


文件差異過大導致無法顯示
+ 319 - 293
examples/jsm/loaders/GLTFLoader.js


+ 16 - 18
examples/jsm/loaders/HDRCubeTextureLoader.js

@@ -15,20 +15,18 @@ import {
 } from '../../../build/three.module.js';
 import { RGBELoader } from '../loaders/RGBELoader.js';
 
-var HDRCubeTextureLoader = function ( manager ) {
+class HDRCubeTextureLoader extends Loader {
 
-	Loader.call( this, manager );
+	constructor( manager ) {
 
-	this.hdrLoader = new RGBELoader();
-	this.type = UnsignedByteType;
+		super( manager );
 
-};
+		this.hdrLoader = new RGBELoader();
+		this.type = UnsignedByteType;
 
-HDRCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
-
-	constructor: HDRCubeTextureLoader,
+	}
 
-	load: function ( urls, onLoad, onProgress, onError ) {
+	load( urls, onLoad, onProgress, onError ) {
 
 		if ( ! Array.isArray( urls ) ) {
 
@@ -43,7 +41,7 @@ HDRCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype
 
 		}
 
-		var texture = new CubeTexture();
+		const texture = new CubeTexture();
 
 		texture.type = this.type;
 
@@ -78,9 +76,9 @@ HDRCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype
 
 		}
 
-		var scope = this;
+		const scope = this;
 
-		var loaded = 0;
+		let loaded = 0;
 
 		function loadHDRData( i, onLoad, onProgress, onError ) {
 
@@ -92,13 +90,13 @@ HDRCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype
 
 					loaded ++;
 
-					var texData = scope.hdrLoader.parse( buffer );
+					const texData = scope.hdrLoader.parse( buffer );
 
 					if ( ! texData ) return;
 
 					if ( texData.data !== undefined ) {
 
-						var dataTexture = new DataTexture( texData.data, texData.width, texData.height );
+						const dataTexture = new DataTexture( texData.data, texData.width, texData.height );
 
 						dataTexture.type = texture.type;
 						dataTexture.encoding = texture.encoding;
@@ -122,7 +120,7 @@ HDRCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype
 
 		}
 
-		for ( var i = 0; i < urls.length; i ++ ) {
+		for ( let i = 0; i < urls.length; i ++ ) {
 
 			loadHDRData( i, onLoad, onProgress, onError );
 
@@ -130,9 +128,9 @@ HDRCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype
 
 		return texture;
 
-	},
+	}
 
-	setDataType: function ( value ) {
+	setDataType( value ) {
 
 		this.type = value;
 		this.hdrLoader.setDataType( value );
@@ -141,6 +139,6 @@ HDRCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype
 
 	}
 
-} );
+}
 
 export { HDRCubeTextureLoader };

+ 32 - 33
examples/jsm/loaders/IFCLoader.js

@@ -16,23 +16,21 @@ import {
 	BufferAttribute,
 } from '../../../build/three.module.js';
 
-var ifcAPI = new IfcAPI();
+const ifcAPI = new IfcAPI();
 
-function IFCLoader( manager ) {
+class IFCLoader extends Loader {
 
-	Loader.call( this, manager );
+	constructor( manager ) {
 
-}
-
-IFCLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
+		super( manager );
 
-	constructor: IFCLoader,
+	}
 
-	load: function ( url, onLoad, onProgress, onError ) {
+	load( url, onLoad, onProgress, onError ) {
 
-		var scope = this;
+		const scope = this;
 
-		var loader = new FileLoader( scope.manager );
+		const loader = new FileLoader( scope.manager );
 		loader.setPath( scope.path );
 		loader.setResponseType( 'arraybuffer' );
 		loader.setRequestHeader( scope.requestHeader );
@@ -66,9 +64,9 @@ IFCLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 			onError
 		);
 
-	},
+	}
 
-	parse: async function ( buffer ) {
+	async parse( buffer ) {
 
 		if ( ifcAPI.wasmModule === undefined ) {
 
@@ -76,18 +74,18 @@ IFCLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
 		}
 
-		var data = new Uint8Array( buffer );
-		var modelID = ifcAPI.OpenModel( 'example.ifc', data );
+		const data = new Uint8Array( buffer );
+		const modelID = ifcAPI.OpenModel( 'example.ifc', data );
 		return loadAllGeometry( modelID );
 
 		function loadAllGeometry( modelID ) {
 
-			var flatMeshes = getFlatMeshes( modelID );
-			var mainObject = new Object3D();
-			for ( var i = 0; i < flatMeshes.size(); i ++ ) {
+			const flatMeshes = getFlatMeshes( modelID );
+			const mainObject = new Object3D();
+			for ( let i = 0; i < flatMeshes.size(); i ++ ) {
 
-				var placedGeometries = flatMeshes.get( i ).geometries;
-				for ( var j = 0; j < placedGeometries.size(); j ++ )
+				const placedGeometries = flatMeshes.get( i ).geometries;
+				for ( let j = 0; j < placedGeometries.size(); j ++ )
 					mainObject.add( getPlacedGeometry( modelID, placedGeometries.get( j ) ) );
 
 			}
@@ -98,16 +96,16 @@ IFCLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
 		function getFlatMeshes( modelID ) {
 
-			var flatMeshes = ifcAPI.LoadAllGeometry( modelID );
+			const flatMeshes = ifcAPI.LoadAllGeometry( modelID );
 			return flatMeshes;
 
 		}
 
 		function getPlacedGeometry( modelID, placedGeometry ) {
 
-			var geometry = getBufferGeometry( modelID, placedGeometry );
-			var material = getMeshMaterial( placedGeometry.color );
-			var mesh = new Mesh( geometry, material );
+			const geometry = getBufferGeometry( modelID, placedGeometry );
+			const material = getMeshMaterial( placedGeometry.color );
+			const mesh = new Mesh( geometry, material );
 			mesh.matrix = getMeshMatrix( placedGeometry.flatTransformation );
 			mesh.matrixAutoUpdate = false;
 			return mesh;
@@ -116,27 +114,27 @@ IFCLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
 		function getBufferGeometry( modelID, placedGeometry ) {
 
-			var geometry = ifcAPI.GetGeometry(
+			const geometry = ifcAPI.GetGeometry(
 				modelID,
 				placedGeometry.geometryExpressID
 			);
-			var verts = ifcAPI.GetVertexArray(
+			const verts = ifcAPI.GetVertexArray(
 				geometry.GetVertexData(),
 				geometry.GetVertexDataSize()
 			);
-			var indices = ifcAPI.GetIndexArray(
+			const indices = ifcAPI.GetIndexArray(
 				geometry.GetIndexData(),
 				geometry.GetIndexDataSize()
 			);
-			var bufferGeometry = ifcGeometryToBuffer( verts, indices );
+			const bufferGeometry = ifcGeometryToBuffer( verts, indices );
 			return bufferGeometry;
 
 		}
 
 		function getMeshMaterial( color ) {
 
-			var col = new Color( color.x, color.y, color.z );
-			var material = new MeshPhongMaterial( { color: col, side: DoubleSide } );
+			const col = new Color( color.x, color.y, color.z );
+			const material = new MeshPhongMaterial( { color: col, side: DoubleSide } );
 			material.transparent = color.w !== 1;
 			if ( material.transparent ) material.opacity = color.w;
 			return material;
@@ -145,7 +143,7 @@ IFCLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
 		function getMeshMatrix( matrix ) {
 
-			var mat = new Matrix4();
+			const mat = new Matrix4();
 			mat.fromArray( matrix );
 			// mat.elements[15 - 3] *= 0.001;
 			// mat.elements[15 - 2] *= 0.001;
@@ -156,8 +154,8 @@ IFCLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
 		function ifcGeometryToBuffer( vertexData, indexData ) {
 
-			var geometry = new BufferGeometry();
-			var buffer32 = new InterleavedBuffer( vertexData, 6 );
+			const geometry = new BufferGeometry();
+			const buffer32 = new InterleavedBuffer( vertexData, 6 );
 			geometry.setAttribute(
 				'position',
 				new InterleavedBufferAttribute( buffer32, 3, 0 )
@@ -172,6 +170,7 @@ IFCLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 		}
 
 	}
-} );
+
+}
 
 export { IFCLoader };

+ 35 - 39
examples/jsm/loaders/KTXLoader.js

@@ -10,19 +10,17 @@ import {
  */
 
 
-var KTXLoader = function ( manager ) {
+class KTXLoader extends CompressedTextureLoader {
 
-	CompressedTextureLoader.call( this, manager );
+	constructor( manager ) {
 
-};
+		super( manager );
 
-KTXLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prototype ), {
-
-	constructor: KTXLoader,
+	}
 
-	parse: function ( buffer, loadMipmaps ) {
+	parse( buffer, loadMipmaps ) {
 
-		var ktx = new KhronosTextureContainer( buffer, 1 );
+		const ktx = new KhronosTextureContainer( buffer, 1 );
 
 		return {
 			mipmaps: ktx.mipmaps( loadMipmaps ),
@@ -35,9 +33,17 @@ KTXLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prot
 
 	}
 
-} );
+}
+
+
+const HEADER_LEN = 12 + ( 13 * 4 ); // identifier + header elements (not including key value meta-data pairs)
+// load types
+const COMPRESSED_2D = 0; // uses a gl.compressedTexImage2D()
+//const COMPRESSED_3D = 1; // uses a gl.compressedTexImage3D()
+//const TEX_2D = 2; // uses a gl.texImage2D()
+//const TEX_3D = 3; // uses a gl.texImage3D()
 
-var KhronosTextureContainer = ( function () {
+class KhronosTextureContainer {
 
 	/**
 	 * @param {ArrayBuffer} arrayBuffer- contents of the KTX container file
@@ -45,14 +51,14 @@ var KhronosTextureContainer = ( function () {
 	 * @param {boolean} threeDExpected- provision for indicating that data should be a 3D texture, not implemented
 	 * @param {boolean} textureArrayExpected- provision for indicating that data should be a texture array, not implemented
 	 */
-	function KhronosTextureContainer( arrayBuffer, facesExpected /*, threeDExpected, textureArrayExpected */ ) {
+	constructor( arrayBuffer, facesExpected /*, threeDExpected, textureArrayExpected */ ) {
 
 		this.arrayBuffer = arrayBuffer;
 
 		// Test that it is a ktx formatted file, based on the first 12 bytes, character representation is:
 		// '´', 'K', 'T', 'X', ' ', '1', '1', 'ª', '\r', '\n', '\x1A', '\n'
 		// 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A
-		var identifier = new Uint8Array( this.arrayBuffer, 0, 12 );
+		const identifier = new Uint8Array( this.arrayBuffer, 0, 12 );
 		if ( identifier[ 0 ] !== 0xAB ||
 			identifier[ 1 ] !== 0x4B ||
 			identifier[ 2 ] !== 0x54 ||
@@ -72,10 +78,10 @@ var KhronosTextureContainer = ( function () {
 		}
 
 		// load the reset of the header in native 32 bit uint
-		var dataSize = Uint32Array.BYTES_PER_ELEMENT;
-		var headerDataView = new DataView( this.arrayBuffer, 12, 13 * dataSize );
-		var endianness = headerDataView.getUint32( 0, true );
-		var littleEndian = endianness === 0x04030201;
+		const dataSize = Uint32Array.BYTES_PER_ELEMENT;
+		const headerDataView = new DataView( this.arrayBuffer, 12, 13 * dataSize );
+		const endianness = headerDataView.getUint32( 0, true );
+		const littleEndian = endianness === 0x04030201;
 
 		this.glType = headerDataView.getUint32( 1 * dataSize, littleEndian ); // must be 0 for compressed textures
 		this.glTypeSize = headerDataView.getUint32( 2 * dataSize, littleEndian ); // must be 1 for compressed textures
@@ -126,29 +132,28 @@ var KhronosTextureContainer = ( function () {
 
 		// we now have a completely validated file, so could use existence of loadType as success
 		// would need to make this more elaborate & adjust checks above to support more than one load type
-		this.loadType = KhronosTextureContainer.COMPRESSED_2D;
+		this.loadType = COMPRESSED_2D;
 
 	}
 
-	// return mipmaps for js
-	KhronosTextureContainer.prototype.mipmaps = function ( loadMipmaps ) {
+	mipmaps( loadMipmaps ) {
 
-		var mipmaps = [];
+		const mipmaps = [];
 
 		// initialize width & height for level 1
-		var dataOffset = KhronosTextureContainer.HEADER_LEN + this.bytesOfKeyValueData;
-		var width = this.pixelWidth;
-		var height = this.pixelHeight;
-		var mipmapCount = loadMipmaps ? this.numberOfMipmapLevels : 1;
+		let dataOffset = HEADER_LEN + this.bytesOfKeyValueData;
+		let width = this.pixelWidth;
+		let height = this.pixelHeight;
+		const mipmapCount = loadMipmaps ? this.numberOfMipmapLevels : 1;
 
-		for ( var level = 0; level < mipmapCount; level ++ ) {
+		for ( let level = 0; level < mipmapCount; level ++ ) {
 
-			var imageSize = new Int32Array( this.arrayBuffer, dataOffset, 1 )[ 0 ]; // size per face, since not supporting array cubemaps
+			const imageSize = new Int32Array( this.arrayBuffer, dataOffset, 1 )[ 0 ]; // size per face, since not supporting array cubemaps
 			dataOffset += 4; // size of the image + 4 for the imageSize field
 
-			for ( var face = 0; face < this.numberOfFaces; face ++ ) {
+			for ( let face = 0; face < this.numberOfFaces; face ++ ) {
 
-				var byteArray = new Uint8Array( this.arrayBuffer, dataOffset, imageSize );
+				const byteArray = new Uint8Array( this.arrayBuffer, dataOffset, imageSize );
 
 				mipmaps.push( { 'data': byteArray, 'width': width, 'height': height } );
 
@@ -164,17 +169,8 @@ var KhronosTextureContainer = ( function () {
 
 		return mipmaps;
 
-	};
-
-	KhronosTextureContainer.HEADER_LEN = 12 + ( 13 * 4 ); // identifier + header elements (not including key value meta-data pairs)
-	// load types
-	KhronosTextureContainer.COMPRESSED_2D = 0; // uses a gl.compressedTexImage2D()
-	KhronosTextureContainer.COMPRESSED_3D = 1; // uses a gl.compressedTexImage3D()
-	KhronosTextureContainer.TEX_2D = 2; // uses a gl.texImage2D()
-	KhronosTextureContainer.TEX_3D = 3; // uses a gl.texImage3D()
-
-	return KhronosTextureContainer;
+	}
 
-}() );
+}
 
 export { KTXLoader };

+ 146 - 159
examples/jsm/loaders/LWOLoader.js

@@ -41,32 +41,28 @@ import {
 
 import { IFFParser } from './lwo/IFFParser.js';
 
-var lwoTree;
+let _lwoTree;
 
-var LWOLoader = function ( manager, parameters ) {
+class LWOLoader extends Loader {
 
-	Loader.call( this, manager );
+	constructor( manager, parameters = {} ) {
 
-	parameters = parameters || {};
+		super( manager );
 
-	this.resourcePath = ( parameters.resourcePath !== undefined ) ? parameters.resourcePath : '';
+		this.resourcePath = ( parameters.resourcePath !== undefined ) ? parameters.resourcePath : '';
 
-};
-
-LWOLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
-
-	constructor: LWOLoader,
+	}
 
-	load: function ( url, onLoad, onProgress, onError ) {
+	load( url, onLoad, onProgress, onError ) {
 
-		var scope = this;
+		const scope = this;
 
-		var path = ( scope.path === '' ) ? extractParentUrl( url, 'Objects' ) : scope.path;
+		const path = ( scope.path === '' ) ? extractParentUrl( url, 'Objects' ) : scope.path;
 
 		// give the mesh a default name based on the filename
-		var modelName = url.split( path ).pop().split( '.' )[ 0 ];
+		const modelName = url.split( path ).pop().split( '.' )[ 0 ];
 
-		var loader = new FileLoader( this.manager );
+		const loader = new FileLoader( this.manager );
 		loader.setPath( scope.path );
 		loader.setResponseType( 'arraybuffer' );
 
@@ -98,34 +94,32 @@ LWOLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
 		}, onProgress, onError );
 
-	},
+	}
 
-	parse: function ( iffBuffer, path, modelName ) {
+	parse( iffBuffer, path, modelName ) {
 
-		lwoTree = new IFFParser().parse( iffBuffer );
+		_lwoTree = new IFFParser().parse( iffBuffer );
 
 		// console.log( 'lwoTree', lwoTree );
 
-		var textureLoader = new TextureLoader( this.manager ).setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin );
+		const textureLoader = new TextureLoader( this.manager ).setPath( this.resourcePath || path ).setCrossOrigin( this.crossOrigin );
 
 		return new LWOTreeParser( textureLoader ).parse( modelName );
 
 	}
 
-} );
+}
 
 // Parse the lwoTree object
-function LWOTreeParser( textureLoader ) {
-
-	this.textureLoader = textureLoader;
+class LWOTreeParser {
 
-}
+	constructor( textureLoader ) {
 
-LWOTreeParser.prototype = {
+		this.textureLoader = textureLoader;
 
-	constructor: LWOTreeParser,
+	}
 
-	parse: function ( modelName ) {
+	parse( modelName ) {
 
 		this.materials = new MaterialParser( this.textureLoader ).parse();
 		this.defaultLayerName = modelName;
@@ -137,24 +131,24 @@ LWOTreeParser.prototype = {
 			meshes: this.meshes,
 		};
 
-	},
+	}
 
 	parseLayers() {
 
 		// array of all meshes for building hierarchy
-		var meshes = [];
+		const meshes = [];
 
 		// final array containing meshes with scene graph hierarchy set up
-		var finalMeshes = [];
+		const finalMeshes = [];
 
-		var geometryParser = new GeometryParser();
+		const geometryParser = new GeometryParser();
 
-		var scope = this;
-		lwoTree.layers.forEach( function ( layer ) {
+		const scope = this;
+		_lwoTree.layers.forEach( function ( layer ) {
 
-			var geometry = geometryParser.parse( layer.geometry, layer );
+			const geometry = geometryParser.parse( layer.geometry, layer );
 
-			var mesh = scope.parseMesh( geometry, layer );
+			const mesh = scope.parseMesh( geometry, layer );
 
 			meshes[ layer.number ] = mesh;
 
@@ -168,13 +162,13 @@ LWOTreeParser.prototype = {
 
 		return finalMeshes;
 
-	},
+	}
 
 	parseMesh( geometry, layer ) {
 
-		var mesh;
+		let mesh;
 
-		var materials = this.getMaterials( geometry.userData.matNames, layer.geometry.type );
+		const materials = this.getMaterials( geometry.userData.matNames, layer.geometry.type );
 
 		this.duplicateUVs( geometry, materials );
 
@@ -189,7 +183,7 @@ LWOTreeParser.prototype = {
 
 		return mesh;
 
-	},
+	}
 
 	// TODO: may need to be reversed in z to convert LWO to three.js coordinates
 	applyPivots( meshes ) {
@@ -198,7 +192,7 @@ LWOTreeParser.prototype = {
 
 			mesh.traverse( function ( child ) {
 
-				var pivot = child.userData.pivot;
+				const pivot = child.userData.pivot;
 
 				child.position.x += pivot[ 0 ];
 				child.position.y += pivot[ 1 ];
@@ -206,7 +200,7 @@ LWOTreeParser.prototype = {
 
 				if ( child.parent ) {
 
-					var parentPivot = child.parent.userData.pivot;
+					const parentPivot = child.parent.userData.pivot;
 
 					child.position.x -= parentPivot[ 0 ];
 					child.position.y -= parentPivot[ 1 ];
@@ -218,13 +212,13 @@ LWOTreeParser.prototype = {
 
 		} );
 
-	},
+	}
 
 	getMaterials( namesArray, type ) {
 
-		var materials = [];
+		const materials = [];
 
-		var scope = this;
+		const scope = this;
 
 		namesArray.forEach( function ( name, i ) {
 
@@ -237,7 +231,7 @@ LWOTreeParser.prototype = {
 
 			materials.forEach( function ( mat, i ) {
 
-				var spec = {
+				const spec = {
 					color: mat.color,
 				};
 
@@ -259,12 +253,12 @@ LWOTreeParser.prototype = {
 		}
 
 		// if there is only one material, return that directly instead of array
-		var filtered = materials.filter( Boolean );
+		const filtered = materials.filter( Boolean );
 		if ( filtered.length === 1 ) return filtered[ 0 ];
 
 		return materials;
 
-	},
+	}
 
 	getMaterialByName( name ) {
 
@@ -274,12 +268,12 @@ LWOTreeParser.prototype = {
 
 		} )[ 0 ];
 
-	},
+	}
 
 	// If the material has an aoMap, duplicate UVs
 	duplicateUVs( geometry, materials ) {
 
-		var duplicateUVs = false;
+		let duplicateUVs = false;
 
 		if ( ! Array.isArray( materials ) ) {
 
@@ -299,34 +293,32 @@ LWOTreeParser.prototype = {
 
 		geometry.setAttribute( 'uv2', new BufferAttribute( geometry.attributes.uv.array, 2 ) );
 
-	},
-
-};
+	}
 
-function MaterialParser( textureLoader ) {
+}
 
-	this.textureLoader = textureLoader;
+class MaterialParser {
 
-}
+	constructor( textureLoader ) {
 
-MaterialParser.prototype = {
+		this.textureLoader = textureLoader;
 
-	constructor: MaterialParser,
+	}
 
-	parse: function () {
+	parse() {
 
-		var materials = [];
+		const materials = [];
 		this.textures = {};
 
-		for ( var name in lwoTree.materials ) {
+		for ( const name in _lwoTree.materials ) {
 
-			if ( lwoTree.format === 'LWO3' ) {
+			if ( _lwoTree.format === 'LWO3' ) {
 
-				materials.push( this.parseMaterial( lwoTree.materials[ name ], name, lwoTree.textures ) );
+				materials.push( this.parseMaterial( _lwoTree.materials[ name ], name, _lwoTree.textures ) );
 
-			} else if ( lwoTree.format === 'LWO2' ) {
+			} else if ( _lwoTree.format === 'LWO2' ) {
 
-				materials.push( this.parseMaterialLwo2( lwoTree.materials[ name ], name, lwoTree.textures ) );
+				materials.push( this.parseMaterialLwo2( _lwoTree.materials[ name ], name, _lwoTree.textures ) );
 
 			}
 
@@ -334,48 +326,48 @@ MaterialParser.prototype = {
 
 		return materials;
 
-	},
+	}
 
 	parseMaterial( materialData, name, textures ) {
 
-		var params = {
+		let params = {
 			name: name,
 			side: this.getSide( materialData.attributes ),
 			flatShading: this.getSmooth( materialData.attributes ),
 		};
 
-		var connections = this.parseConnections( materialData.connections, materialData.nodes );
+		const connections = this.parseConnections( materialData.connections, materialData.nodes );
 
-		var maps = this.parseTextureNodes( connections.maps );
+		const maps = this.parseTextureNodes( connections.maps );
 
 		this.parseAttributeImageMaps( connections.attributes, textures, maps, materialData.maps );
 
-		var attributes = this.parseAttributes( connections.attributes, maps );
+		const attributes = this.parseAttributes( connections.attributes, maps );
 
 		this.parseEnvMap( connections, maps, attributes );
 
 		params = Object.assign( maps, params );
 		params = Object.assign( params, attributes );
 
-		var materialType = this.getMaterialType( connections.attributes );
+		const materialType = this.getMaterialType( connections.attributes );
 
 		return new materialType( params );
 
-	},
+	}
 
 	parseMaterialLwo2( materialData, name/*, textures*/ ) {
 
-		var params = {
+		let params = {
 			name: name,
 			side: this.getSide( materialData.attributes ),
 			flatShading: this.getSmooth( materialData.attributes ),
 		};
 
-		var attributes = this.parseAttributes( materialData.attributes, {} );
+		const attributes = this.parseAttributes( materialData.attributes, {} );
 		params = Object.assign( params, attributes );
 		return new MeshPhongMaterial( params );
 
-	},
+	}
 
 	// Note: converting from left to right handed coords by switching x -> -x in vertices, and
 	// then switching mat FrontSide -> BackSide
@@ -394,31 +386,31 @@ MaterialParser.prototype = {
 
 		}
 
-	},
+	}
 
 	getSmooth( attributes ) {
 
 		if ( ! attributes.smooth ) return true;
 		return ! attributes.smooth;
 
-	},
+	}
 
 	parseConnections( connections, nodes ) {
 
-		var materialConnections = {
+		const materialConnections = {
 			maps: {}
 		};
 
-		var inputName = connections.inputName;
-		var inputNodeName = connections.inputNodeName;
-		var nodeName = connections.nodeName;
+		const inputName = connections.inputName;
+		const inputNodeName = connections.inputNodeName;
+		const nodeName = connections.nodeName;
 
-		var scope = this;
+		const scope = this;
 		inputName.forEach( function ( name, index ) {
 
 			if ( name === 'Material' ) {
 
-				var matNode = scope.getNodeByRefName( inputNodeName[ index ], nodes );
+				const matNode = scope.getNodeByRefName( inputNodeName[ index ], nodes );
 				materialConnections.attributes = matNode.attributes;
 				materialConnections.envMap = matNode.fileName;
 				materialConnections.name = inputNodeName[ index ];
@@ -439,30 +431,30 @@ MaterialParser.prototype = {
 
 		return materialConnections;
 
-	},
+	}
 
 	getNodeByRefName( refName, nodes ) {
 
-		for ( var name in nodes ) {
+		for ( const name in nodes ) {
 
 			if ( nodes[ name ].refName === refName ) return nodes[ name ];
 
 		}
 
-	},
+	}
 
 	parseTextureNodes( textureNodes ) {
 
-		var maps = {};
+		const maps = {};
 
-		for ( var name in textureNodes ) {
+		for ( const name in textureNodes ) {
 
-			var node = textureNodes[ name ];
-			var path = node.fileName;
+			const node = textureNodes[ name ];
+			const path = node.fileName;
 
 			if ( ! path ) return;
 
-			var texture = this.loadTexture( path );
+			const texture = this.loadTexture( path );
 
 			if ( node.widthWrappingMode !== undefined ) texture.wrapS = this.getWrappingType( node.widthWrappingMode );
 			if ( node.heightWrappingMode !== undefined ) texture.wrapT = this.getWrappingType( node.heightWrappingMode );
@@ -513,24 +505,24 @@ MaterialParser.prototype = {
 
 		return maps;
 
-	},
+	}
 
 	// maps can also be defined on individual material attributes, parse those here
 	// This occurs on Standard (Phong) surfaces
 	parseAttributeImageMaps( attributes, textures, maps ) {
 
-		for ( var name in attributes ) {
+		for ( const name in attributes ) {
 
-			var attribute = attributes[ name ];
+			const attribute = attributes[ name ];
 
 			if ( attribute.maps ) {
 
-				var mapData = attribute.maps[ 0 ];
+				const mapData = attribute.maps[ 0 ];
 
-				var path = this.getTexturePathByIndex( mapData.imageIndex, textures );
+				const path = this.getTexturePathByIndex( mapData.imageIndex, textures );
 				if ( ! path ) return;
 
-				var texture = this.loadTexture( path );
+				const texture = this.loadTexture( path );
 
 				if ( mapData.wrap !== undefined ) texture.wrapS = this.getWrappingType( mapData.wrap.w );
 				if ( mapData.wrap !== undefined ) texture.wrapT = this.getWrappingType( mapData.wrap.h );
@@ -577,11 +569,11 @@ MaterialParser.prototype = {
 
 		}
 
-	},
+	}
 
 	parseAttributes( attributes, maps ) {
 
-		var params = {};
+		const params = {};
 
 		// don't use color data if color map is present
 		if ( attributes.Color && ! maps.map ) {
@@ -608,7 +600,7 @@ MaterialParser.prototype = {
 
 		return params;
 
-	},
+	}
 
 	parsePhysicalAttributes( params, attributes/*, maps*/ ) {
 
@@ -624,7 +616,7 @@ MaterialParser.prototype = {
 
 		}
 
-	},
+	}
 
 	parseStandardAttributes( params, attributes, maps ) {
 
@@ -648,7 +640,7 @@ MaterialParser.prototype = {
 		if ( attributes.Roughness && ! maps.roughnessMap ) params.roughness = attributes.Roughness.value;
 		if ( attributes.Metallic && ! maps.metalnessMap ) params.metalness = attributes.Metallic.value;
 
-	},
+	}
 
 	parsePhongAttributes( params, attributes, maps ) {
 
@@ -694,13 +686,13 @@ MaterialParser.prototype = {
 
 		if ( params.specular && attributes.Glossiness ) params.shininess = 7 + Math.pow( 2, attributes.Glossiness.value * 12 + 2 );
 
-	},
+	}
 
 	parseEnvMap( connections, maps, attributes ) {
 
 		if ( connections.envMap ) {
 
-			var envMap = this.loadTexture( connections.envMap );
+			const envMap = this.loadTexture( connections.envMap );
 
 			if ( attributes.transparent && attributes.opacity < 0.999 ) {
 
@@ -726,16 +718,16 @@ MaterialParser.prototype = {
 
 		}
 
-	},
+	}
 
 	// get texture defined at top level by its index
 	getTexturePathByIndex( index ) {
 
-		var fileName = '';
+		let fileName = '';
 
-		if ( ! lwoTree.textures ) return fileName;
+		if ( ! _lwoTree.textures ) return fileName;
 
-		lwoTree.textures.forEach( function ( texture ) {
+		_lwoTree.textures.forEach( function ( texture ) {
 
 			if ( texture.index === index ) fileName = texture.fileName;
 
@@ -743,15 +735,13 @@ MaterialParser.prototype = {
 
 		return fileName;
 
-	},
+	}
 
 	loadTexture( path ) {
 
 		if ( ! path ) return null;
 
-		var texture;
-
-		texture = this.textureLoader.load(
+		const texture = this.textureLoader.load(
 			path,
 			undefined,
 			undefined,
@@ -764,7 +754,7 @@ MaterialParser.prototype = {
 
 		return texture;
 
-	},
+	}
 
 	// 0 = Reset, 1 = Repeat, 2 = Mirror, 3 = Edge
 	getWrappingType( num ) {
@@ -780,7 +770,7 @@ MaterialParser.prototype = {
 
 		}
 
-	},
+	}
 
 	getMaterialType( nodeData ) {
 
@@ -790,21 +780,17 @@ MaterialParser.prototype = {
 
 	}
 
-};
-
-function GeometryParser() {}
-
-GeometryParser.prototype = {
+}
 
-	constructor: GeometryParser,
+class GeometryParser {
 
 	parse( geoData, layer ) {
 
-		var geometry = new BufferGeometry();
+		const geometry = new BufferGeometry();
 
 		geometry.setAttribute( 'position', new Float32BufferAttribute( geoData.points, 3 ) );
 
-		var indices = this.splitIndices( geoData.vertexIndices, geoData.polygonDimensions );
+		const indices = this.splitIndices( geoData.vertexIndices, geoData.polygonDimensions );
 		geometry.setIndex( indices );
 
 		this.parseGroups( geometry, geoData );
@@ -817,25 +803,25 @@ GeometryParser.prototype = {
 		// TODO: z may need to be reversed to account for coordinate system change
 		geometry.translate( - layer.pivot[ 0 ], - layer.pivot[ 1 ], - layer.pivot[ 2 ] );
 
-		// var userData = geometry.userData;
+		// let userData = geometry.userData;
 		// geometry = geometry.toNonIndexed()
 		// geometry.userData = userData;
 
 		return geometry;
 
-	},
+	}
 
 	// split quads into tris
 	splitIndices( indices, polygonDimensions ) {
 
-		var remappedIndices = [];
+		const remappedIndices = [];
 
-		var i = 0;
+		let i = 0;
 		polygonDimensions.forEach( function ( dim ) {
 
 			if ( dim < 4 ) {
 
-				for ( var k = 0; k < dim; k ++ ) remappedIndices.push( indices[ i + k ] );
+				for ( let k = 0; k < dim; k ++ ) remappedIndices.push( indices[ i + k ] );
 
 			} else if ( dim === 4 ) {
 
@@ -852,7 +838,7 @@ GeometryParser.prototype = {
 
 			} else if ( dim > 4 ) {
 
-				for ( var k = 1; k < dim - 1; k ++ ) {
+				for ( let k = 1; k < dim - 1; k ++ ) {
 
 					remappedIndices.push( indices[ i ], indices[ i + k ], indices[ i + k + 1 ] );
 
@@ -868,31 +854,32 @@ GeometryParser.prototype = {
 
 		return remappedIndices;
 
-	},
+	}
 
 	// NOTE: currently ignoring poly indices and assuming that they are intelligently ordered
 	parseGroups( geometry, geoData ) {
 
-		var tags = lwoTree.tags;
-		var matNames = [];
+		const tags = _lwoTree.tags;
+		const matNames = [];
 
-		var elemSize = 3;
+		let elemSize = 3;
 		if ( geoData.type === 'lines' ) elemSize = 2;
 		if ( geoData.type === 'points' ) elemSize = 1;
 
-		var remappedIndices = this.splitMaterialIndices( geoData.polygonDimensions, geoData.materialIndices );
+		const remappedIndices = this.splitMaterialIndices( geoData.polygonDimensions, geoData.materialIndices );
 
-		var indexNum = 0; // create new indices in numerical order
-		var indexPairs = {}; // original indices mapped to numerical indices
+		let indexNum = 0; // create new indices in numerical order
+		const indexPairs = {}; // original indices mapped to numerical indices
 
-		var prevMaterialIndex;
+		let prevMaterialIndex;
+		let materialIndex;
 
-		var prevStart = 0;
-		var currentCount = 0;
+		let prevStart = 0;
+		let currentCount = 0;
 
-		for ( var i = 0; i < remappedIndices.length; i += 2 ) {
+		for ( let i = 0; i < remappedIndices.length; i += 2 ) {
 
-			var materialIndex = remappedIndices[ i + 1 ];
+			materialIndex = remappedIndices[ i + 1 ];
 
 			if ( i === 0 ) matNames[ indexNum ] = tags[ materialIndex ];
 
@@ -900,7 +887,7 @@ GeometryParser.prototype = {
 
 			if ( materialIndex !== prevMaterialIndex ) {
 
-				var currentIndex;
+				let currentIndex;
 				if ( indexPairs[ tags[ prevMaterialIndex ] ] ) {
 
 					currentIndex = indexPairs[ tags[ prevMaterialIndex ] ];
@@ -930,7 +917,7 @@ GeometryParser.prototype = {
 		// the loop above doesn't add the last group, do that here.
 		if ( geometry.groups.length > 0 ) {
 
-			var currentIndex;
+			let currentIndex;
 			if ( indexPairs[ tags[ materialIndex ] ] ) {
 
 				currentIndex = indexPairs[ tags[ materialIndex ] ];
@@ -950,11 +937,11 @@ GeometryParser.prototype = {
 		// Mat names from TAGS chunk, used to build up an array of materials for this geometry
 		geometry.userData.matNames = matNames;
 
-	},
+	}
 
 	splitMaterialIndices( polygonDimensions, indices ) {
 
-		var remappedIndices = [];
+		const remappedIndices = [];
 
 		polygonDimensions.forEach( function ( dim, i ) {
 
@@ -969,7 +956,7 @@ GeometryParser.prototype = {
 			} else {
 
 				 // ignore > 4 for now
-				for ( var k = 0; k < dim - 2; k ++ ) {
+				for ( let k = 0; k < dim - 2; k ++ ) {
 
 					remappedIndices.push( indices[ i * 2 ], indices[ i * 2 + 1 ] );
 
@@ -981,7 +968,7 @@ GeometryParser.prototype = {
 
 		return remappedIndices;
 
-	},
+	}
 
 	// UV maps:
 	// 1: are defined via index into an array of points, not into a geometry
@@ -995,16 +982,16 @@ GeometryParser.prototype = {
 	parseUVs( geometry, layer ) {
 
 		// start by creating a UV map set to zero for the whole geometry
-		var remappedUVs = Array.from( Array( geometry.attributes.position.count * 2 ), function () {
+		const remappedUVs = Array.from( Array( geometry.attributes.position.count * 2 ), function () {
 
 			return 0;
 
 		} );
 
-		for ( var name in layer.uvs ) {
+		for ( const name in layer.uvs ) {
 
-			var uvs = layer.uvs[ name ].uvs;
-			var uvIndices = layer.uvs[ name ].uvIndices;
+			const uvs = layer.uvs[ name ].uvs;
+			const uvIndices = layer.uvs[ name ].uvIndices;
 
 			uvIndices.forEach( function ( i, j ) {
 
@@ -1017,20 +1004,20 @@ GeometryParser.prototype = {
 
 		geometry.setAttribute( 'uv', new Float32BufferAttribute( remappedUVs, 2 ) );
 
-	},
+	}
 
 	parseMorphTargets( geometry, layer ) {
 
-		var num = 0;
-		for ( var name in layer.morphTargets ) {
+		let num = 0;
+		for ( const name in layer.morphTargets ) {
 
-			var remappedPoints = geometry.attributes.position.array.slice();
+			const remappedPoints = geometry.attributes.position.array.slice();
 
 			if ( ! geometry.morphAttributes.position ) geometry.morphAttributes.position = [];
 
-			var morphPoints = layer.morphTargets[ name ].points;
-			var morphIndices = layer.morphTargets[ name ].indices;
-			var type = layer.morphTargets[ name ].type;
+			const morphPoints = layer.morphTargets[ name ].points;
+			const morphIndices = layer.morphTargets[ name ].indices;
+			const type = layer.morphTargets[ name ].type;
 
 			morphIndices.forEach( function ( i, j ) {
 
@@ -1059,16 +1046,16 @@ GeometryParser.prototype = {
 
 		geometry.morphTargetsRelative = false;
 
-	},
+	}
 
-};
+}
 
 
 // ************** UTILITY FUNCTIONS **************
 
 function extractParentUrl( url, dir ) {
 
-	var index = url.indexOf( dir );
+	const index = url.indexOf( dir );
 
 	if ( index === - 1 ) return './';
 

+ 85 - 89
examples/jsm/loaders/MTLLoader.js

@@ -15,15 +15,13 @@ import {
  * Loads a Wavefront .mtl file specifying materials
  */
 
-var MTLLoader = function ( manager ) {
+class MTLLoader extends Loader {
 
-	Loader.call( this, manager );
+	constructor( manager ) {
 
-};
+		super( manager );
 
-MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
-
-	constructor: MTLLoader,
+	}
 
 	/**
 	 * Loads and parses a MTL asset from a URL.
@@ -38,13 +36,13 @@ MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 	 * @note In order for relative texture references to resolve correctly
 	 * you must call setResourcePath() explicitly prior to load.
 	 */
-	load: function ( url, onLoad, onProgress, onError ) {
+	load( url, onLoad, onProgress, onError ) {
 
-		var scope = this;
+		const scope = this;
 
-		var path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
+		const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
 
-		var loader = new FileLoader( this.manager );
+		const loader = new FileLoader( this.manager );
 		loader.setPath( this.path );
 		loader.setRequestHeader( this.requestHeader );
 		loader.setWithCredentials( this.withCredentials );
@@ -72,36 +70,36 @@ MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
 		}, onProgress, onError );
 
-	},
+	}
 
-	setMaterialOptions: function ( value ) {
+	setMaterialOptions( value ) {
 
 		this.materialOptions = value;
 		return this;
 
-	},
+	}
 
 	/**
 	 * Parses a MTL file.
 	 *
 	 * @param {String} text - Content of MTL file
-	 * @return {MTLLoader.MaterialCreator}
+	 * @return {MaterialCreator}
 	 *
 	 * @see setPath setResourcePath
 	 *
 	 * @note In order for relative texture references to resolve correctly
 	 * you must call setResourcePath() explicitly prior to parse.
 	 */
-	parse: function ( text, path ) {
+	parse( text, path ) {
 
-		var lines = text.split( '\n' );
-		var info = {};
-		var delimiter_pattern = /\s+/;
-		var materialsInfo = {};
+		const lines = text.split( '\n' );
+		let info = {};
+		const delimiter_pattern = /\s+/;
+		const materialsInfo = {};
 
-		for ( var i = 0; i < lines.length; i ++ ) {
+		for ( let i = 0; i < lines.length; i ++ ) {
 
-			var line = lines[ i ];
+			let line = lines[ i ];
 			line = line.trim();
 
 			if ( line.length === 0 || line.charAt( 0 ) === '#' ) {
@@ -111,12 +109,12 @@ MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
 			}
 
-			var pos = line.indexOf( ' ' );
+			const pos = line.indexOf( ' ' );
 
-			var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line;
+			let key = ( pos >= 0 ) ? line.substring( 0, pos ) : line;
 			key = key.toLowerCase();
 
-			var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : '';
+			let value = ( pos >= 0 ) ? line.substring( pos + 1 ) : '';
 			value = value.trim();
 
 			if ( key === 'newmtl' ) {
@@ -130,7 +128,7 @@ MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
 				if ( key === 'ka' || key === 'kd' || key === 'ks' || key === 'ke' ) {
 
-					var ss = value.split( delimiter_pattern, 3 );
+					const ss = value.split( delimiter_pattern, 3 );
 					info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ];
 
 				} else {
@@ -143,7 +141,7 @@ MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
 		}
 
-		var materialCreator = new MTLLoader.MaterialCreator( this.resourcePath || path, this.materialOptions );
+		const materialCreator = new MaterialCreator( this.resourcePath || path, this.materialOptions );
 		materialCreator.setCrossOrigin( this.crossOrigin );
 		materialCreator.setManager( this.manager );
 		materialCreator.setMaterials( materialsInfo );
@@ -151,7 +149,7 @@ MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 
 	}
 
-} );
+}
 
 /**
  * Create a new MTLLoader.MaterialCreator
@@ -168,69 +166,67 @@ MTLLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
  * @constructor
  */
 
-MTLLoader.MaterialCreator = function ( baseUrl, options ) {
-
-	this.baseUrl = baseUrl || '';
-	this.options = options;
-	this.materialsInfo = {};
-	this.materials = {};
-	this.materialsArray = [];
-	this.nameLookup = {};
+class MaterialCreator {
 
-	this.side = ( this.options && this.options.side ) ? this.options.side : FrontSide;
-	this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : RepeatWrapping;
+	constructor( baseUrl = '', options = {} ) {
 
-};
+		this.baseUrl = baseUrl;
+		this.options = options;
+		this.materialsInfo = {};
+		this.materials = {};
+		this.materialsArray = [];
+		this.nameLookup = {};
 
-MTLLoader.MaterialCreator.prototype = {
+		this.crossOrigin = 'anonymous';
 
-	constructor: MTLLoader.MaterialCreator,
+		this.side = ( this.options.side !== undefined ) ? this.options.side : FrontSide;
+		this.wrap = ( this.options.wrap !== undefined ) ? this.options.wrap : RepeatWrapping;
 
-	crossOrigin: 'anonymous',
+	}
 
-	setCrossOrigin: function ( value ) {
+	setCrossOrigin( value ) {
 
 		this.crossOrigin = value;
 		return this;
 
-	},
+	}
 
-	setManager: function ( value ) {
+	setManager( value ) {
 
 		this.manager = value;
 
-	},
+	}
 
-	setMaterials: function ( materialsInfo ) {
+	setMaterials( materialsInfo ) {
 
 		this.materialsInfo = this.convert( materialsInfo );
 		this.materials = {};
 		this.materialsArray = [];
 		this.nameLookup = {};
 
-	},
+	}
 
-	convert: function ( materialsInfo ) {
+	convert( materialsInfo ) {
 
 		if ( ! this.options ) return materialsInfo;
 
-		var converted = {};
+		const converted = {};
 
-		for ( var mn in materialsInfo ) {
+		for ( const mn in materialsInfo ) {
 
 			// Convert materials info into normalized form based on options
 
-			var mat = materialsInfo[ mn ];
+			const mat = materialsInfo[ mn ];
 
-			var covmat = {};
+			const covmat = {};
 
 			converted[ mn ] = covmat;
 
-			for ( var prop in mat ) {
+			for ( const prop in mat ) {
 
-				var save = true;
-				var value = mat[ prop ];
-				var lprop = prop.toLowerCase();
+				let save = true;
+				let value = mat[ prop ];
+				const lprop = prop.toLowerCase();
 
 				switch ( lprop ) {
 
@@ -278,29 +274,29 @@ MTLLoader.MaterialCreator.prototype = {
 
 		return converted;
 
-	},
+	}
 
-	preload: function () {
+	preload() {
 
-		for ( var mn in this.materialsInfo ) {
+		for ( const mn in this.materialsInfo ) {
 
 			this.create( mn );
 
 		}
 
-	},
+	}
 
-	getIndex: function ( materialName ) {
+	getIndex( materialName ) {
 
 		return this.nameLookup[ materialName ];
 
-	},
+	}
 
-	getAsArray: function () {
+	getAsArray() {
 
-		var index = 0;
+		let index = 0;
 
-		for ( var mn in this.materialsInfo ) {
+		for ( const mn in this.materialsInfo ) {
 
 			this.materialsArray[ index ] = this.create( mn );
 			this.nameLookup[ mn ] = index;
@@ -310,9 +306,9 @@ MTLLoader.MaterialCreator.prototype = {
 
 		return this.materialsArray;
 
-	},
+	}
 
-	create: function ( materialName ) {
+	create( materialName ) {
 
 		if ( this.materials[ materialName ] === undefined ) {
 
@@ -322,15 +318,15 @@ MTLLoader.MaterialCreator.prototype = {
 
 		return this.materials[ materialName ];
 
-	},
+	}
 
-	createMaterial_: function ( materialName ) {
+	createMaterial_( materialName ) {
 
 		// Create material
 
-		var scope = this;
-		var mat = this.materialsInfo[ materialName ];
-		var params = {
+		const scope = this;
+		const mat = this.materialsInfo[ materialName ];
+		const params = {
 
 			name: materialName,
 			side: this.side
@@ -353,8 +349,8 @@ MTLLoader.MaterialCreator.prototype = {
 
 			if ( params[ mapType ] ) return; // Keep the first encountered texture
 
-			var texParams = scope.getTextureParams( value, params );
-			var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) );
+			const texParams = scope.getTextureParams( value, params );
+			const map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) );
 
 			map.repeat.copy( texParams.scale );
 			map.offset.copy( texParams.offset );
@@ -366,10 +362,10 @@ MTLLoader.MaterialCreator.prototype = {
 
 		}
 
-		for ( var prop in mat ) {
+		for ( const prop in mat ) {
 
-			var value = mat[ prop ];
-			var n;
+			const value = mat[ prop ];
+			let n;
 
 			if ( value === '' ) continue;
 
@@ -492,19 +488,19 @@ MTLLoader.MaterialCreator.prototype = {
 		this.materials[ materialName ] = new MeshPhongMaterial( params );
 		return this.materials[ materialName ];
 
-	},
+	}
 
-	getTextureParams: function ( value, matParams ) {
+	getTextureParams( value, matParams ) {
 
-		var texParams = {
+		const texParams = {
 
 			scale: new Vector2( 1, 1 ),
 			offset: new Vector2( 0, 0 )
 
 		 };
 
-		var items = value.split( /\s+/ );
-		var pos;
+		const items = value.split( /\s+/ );
+		let pos;
 
 		pos = items.indexOf( '-bm' );
 
@@ -536,13 +532,12 @@ MTLLoader.MaterialCreator.prototype = {
 		texParams.url = items.join( ' ' ).trim();
 		return texParams;
 
-	},
+	}
 
-	loadTexture: function ( url, mapping, onLoad, onProgress, onError ) {
+	loadTexture( url, mapping, onLoad, onProgress, onError ) {
 
-		var texture;
-		var manager = ( this.manager !== undefined ) ? this.manager : DefaultLoadingManager;
-		var loader = manager.getHandler( url );
+		const manager = ( this.manager !== undefined ) ? this.manager : DefaultLoadingManager;
+		let loader = manager.getHandler( url );
 
 		if ( loader === null ) {
 
@@ -551,7 +546,8 @@ MTLLoader.MaterialCreator.prototype = {
 		}
 
 		if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin );
-		texture = loader.load( url, onLoad, onProgress, onError );
+
+		const texture = loader.load( url, onLoad, onProgress, onError );
 
 		if ( mapping !== undefined ) texture.mapping = mapping;
 
@@ -559,6 +555,6 @@ MTLLoader.MaterialCreator.prototype = {
 
 	}
 
-};
+}
 
 export { MTLLoader };

文件差異過大導致無法顯示
+ 411 - 414
examples/jsm/loaders/OBJLoader.js


+ 168 - 185
examples/jsm/loaders/PRWMLoader.js

@@ -9,308 +9,291 @@ import {
  * See https://github.com/kchapelier/PRWM for more informations about this file format
  */
 
-var PRWMLoader = ( function () {
+let bigEndianPlatform = null;
 
-	var bigEndianPlatform = null;
-
-	/**
+/**
 	 * Check if the endianness of the platform is big-endian (most significant bit first)
 	 * @returns {boolean} True if big-endian, false if little-endian
 	 */
-	function isBigEndianPlatform() {
+function isBigEndianPlatform() {
 
-		if ( bigEndianPlatform === null ) {
+	if ( bigEndianPlatform === null ) {
 
-			var buffer = new ArrayBuffer( 2 ),
-				uint8Array = new Uint8Array( buffer ),
-				uint16Array = new Uint16Array( buffer );
+		const buffer = new ArrayBuffer( 2 ),
+			uint8Array = new Uint8Array( buffer ),
+			uint16Array = new Uint16Array( buffer );
 
-			uint8Array[ 0 ] = 0xAA; // set first byte
-			uint8Array[ 1 ] = 0xBB; // set second byte
-			bigEndianPlatform = ( uint16Array[ 0 ] === 0xAABB );
+		uint8Array[ 0 ] = 0xAA; // set first byte
+		uint8Array[ 1 ] = 0xBB; // set second byte
+		bigEndianPlatform = ( uint16Array[ 0 ] === 0xAABB );
 
-		}
+	}
 
-		return bigEndianPlatform;
+	return bigEndianPlatform;
 
-	}
+}
 
-	// match the values defined in the spec to the TypedArray types
-	var InvertedEncodingTypes = [
-		null,
-		Float32Array,
-		null,
-		Int8Array,
-		Int16Array,
-		null,
-		Int32Array,
-		Uint8Array,
-		Uint16Array,
-		null,
-		Uint32Array
-	];
-
-	// define the method to use on a DataView, corresponding the TypedArray type
-	var getMethods = {
-		Uint16Array: 'getUint16',
-		Uint32Array: 'getUint32',
-		Int16Array: 'getInt16',
-		Int32Array: 'getInt32',
-		Float32Array: 'getFloat32',
-		Float64Array: 'getFloat64'
-	};
+// match the values defined in the spec to the TypedArray types
+const InvertedEncodingTypes = [
+	null,
+	Float32Array,
+	null,
+	Int8Array,
+	Int16Array,
+	null,
+	Int32Array,
+	Uint8Array,
+	Uint16Array,
+	null,
+	Uint32Array
+];
 
+// define the method to use on a DataView, corresponding the TypedArray type
+const getMethods = {
+	Uint16Array: 'getUint16',
+	Uint32Array: 'getUint32',
+	Int16Array: 'getInt16',
+	Int32Array: 'getInt32',
+	Float32Array: 'getFloat32',
+	Float64Array: 'getFloat64'
+};
 
-	function copyFromBuffer( sourceArrayBuffer, viewType, position, length, fromBigEndian ) {
 
-		var bytesPerElement = viewType.BYTES_PER_ELEMENT,
-			result;
+function copyFromBuffer( sourceArrayBuffer, viewType, position, length, fromBigEndian ) {
 
-		if ( fromBigEndian === isBigEndianPlatform() || bytesPerElement === 1 ) {
+	const bytesPerElement = viewType.BYTES_PER_ELEMENT;
+	let result;
 
-			result = new viewType( sourceArrayBuffer, position, length );
+	if ( fromBigEndian === isBigEndianPlatform() || bytesPerElement === 1 ) {
 
-		} else {
+		result = new viewType( sourceArrayBuffer, position, length );
 
-			var readView = new DataView( sourceArrayBuffer, position, length * bytesPerElement ),
-				getMethod = getMethods[ viewType.name ],
-				littleEndian = ! fromBigEndian,
-				i = 0;
+	} else {
 
-			result = new viewType( length );
+		const readView = new DataView( sourceArrayBuffer, position, length * bytesPerElement ),
+			getMethod = getMethods[ viewType.name ],
+			littleEndian = ! fromBigEndian;
 
-			for ( ; i < length; i ++ ) {
+		result = new viewType( length );
 
-				result[ i ] = readView[ getMethod ]( i * bytesPerElement, littleEndian );
+		for ( let i = 0; i < length; i ++ ) {
 
-			}
+			result[ i ] = readView[ getMethod ]( i * bytesPerElement, littleEndian );
 
 		}
 
-		return result;
-
 	}
 
+	return result;
 
-	function decodePrwm( buffer ) {
+}
 
-		var array = new Uint8Array( buffer ),
-			version = array[ 0 ],
-			flags = array[ 1 ],
-			indexedGeometry = !! ( flags >> 7 & 0x01 ),
-			indicesType = flags >> 6 & 0x01,
-			bigEndian = ( flags >> 5 & 0x01 ) === 1,
-			attributesNumber = flags & 0x1F,
-			valuesNumber = 0,
-			indicesNumber = 0;
 
-		if ( bigEndian ) {
+function decodePrwm( buffer ) {
 
-			valuesNumber = ( array[ 2 ] << 16 ) + ( array[ 3 ] << 8 ) + array[ 4 ];
-			indicesNumber = ( array[ 5 ] << 16 ) + ( array[ 6 ] << 8 ) + array[ 7 ];
+	const array = new Uint8Array( buffer ),
+		version = array[ 0 ];
 
-		} else {
+	let flags = array[ 1 ];
 
-			valuesNumber = array[ 2 ] + ( array[ 3 ] << 8 ) + ( array[ 4 ] << 16 );
-			indicesNumber = array[ 5 ] + ( array[ 6 ] << 8 ) + ( array[ 7 ] << 16 );
+	const indexedGeometry = !! ( flags >> 7 & 0x01 ),
+		indicesType = flags >> 6 & 0x01,
+		bigEndian = ( flags >> 5 & 0x01 ) === 1,
+		attributesNumber = flags & 0x1F;
 
-		}
+	let valuesNumber = 0,
+		indicesNumber = 0;
 
-		/** PRELIMINARY CHECKS **/
+	if ( bigEndian ) {
 
-		if ( version === 0 ) {
+		valuesNumber = ( array[ 2 ] << 16 ) + ( array[ 3 ] << 8 ) + array[ 4 ];
+		indicesNumber = ( array[ 5 ] << 16 ) + ( array[ 6 ] << 8 ) + array[ 7 ];
 
-			throw new Error( 'PRWM decoder: Invalid format version: 0' );
+	} else {
 
-		} else if ( version !== 1 ) {
+		valuesNumber = array[ 2 ] + ( array[ 3 ] << 8 ) + ( array[ 4 ] << 16 );
+		indicesNumber = array[ 5 ] + ( array[ 6 ] << 8 ) + ( array[ 7 ] << 16 );
 
-			throw new Error( 'PRWM decoder: Unsupported format version: ' + version );
+	}
 
-		}
+	/** PRELIMINARY CHECKS **/
 
-		if ( ! indexedGeometry ) {
+	if ( version === 0 ) {
 
-			if ( indicesType !== 0 ) {
+		throw new Error( 'PRWM decoder: Invalid format version: 0' );
 
-				throw new Error( 'PRWM decoder: Indices type must be set to 0 for non-indexed geometries' );
+	} else if ( version !== 1 ) {
 
-			} else if ( indicesNumber !== 0 ) {
+		throw new Error( 'PRWM decoder: Unsupported format version: ' + version );
 
-				throw new Error( 'PRWM decoder: Number of indices must be set to 0 for non-indexed geometries' );
+	}
 
-			}
+	if ( ! indexedGeometry ) {
 
-		}
+		if ( indicesType !== 0 ) {
 
-		/** PARSING **/
+			throw new Error( 'PRWM decoder: Indices type must be set to 0 for non-indexed geometries' );
 
-		var pos = 8;
+		} else if ( indicesNumber !== 0 ) {
 
-		var attributes = {},
-			attributeName,
-			char,
-			attributeType,
-			cardinality,
-			encodingType,
-			arrayType,
-			values,
-			indices,
-			i;
+			throw new Error( 'PRWM decoder: Number of indices must be set to 0 for non-indexed geometries' );
 
-		for ( i = 0; i < attributesNumber; i ++ ) {
+		}
 
-			attributeName = '';
+	}
 
-			while ( pos < array.length ) {
+	/** PARSING **/
 
-				char = array[ pos ];
-				pos ++;
+	let pos = 8;
 
-				if ( char === 0 ) {
+	const attributes = {};
 
-					break;
+	for ( let i = 0; i < attributesNumber; i ++ ) {
 
-				} else {
+		let attributeName = '';
 
-					attributeName += String.fromCharCode( char );
+		while ( pos < array.length ) {
 
-				}
+			const char = array[ pos ];
+			pos ++;
 
-			}
+			if ( char === 0 ) {
 
-			flags = array[ pos ];
+				break;
 
-			attributeType = flags >> 7 & 0x01;
-			cardinality = ( flags >> 4 & 0x03 ) + 1;
-			encodingType = flags & 0x0F;
-			arrayType = InvertedEncodingTypes[ encodingType ];
+			} else {
 
-			pos ++;
+				attributeName += String.fromCharCode( char );
 
-			// padding to next multiple of 4
-			pos = Math.ceil( pos / 4 ) * 4;
+			}
 
-			values = copyFromBuffer( buffer, arrayType, pos, cardinality * valuesNumber, bigEndian );
+		}
 
-			pos += arrayType.BYTES_PER_ELEMENT * cardinality * valuesNumber;
+		flags = array[ pos ];
 
-			attributes[ attributeName ] = {
-				type: attributeType,
-				cardinality: cardinality,
-				values: values
-			};
+		const attributeType = flags >> 7 & 0x01;
+		const cardinality = ( flags >> 4 & 0x03 ) + 1;
+		const encodingType = flags & 0x0F;
+		const arrayType = InvertedEncodingTypes[ encodingType ];
 
-		}
+		pos ++;
 
+		// padding to next multiple of 4
 		pos = Math.ceil( pos / 4 ) * 4;
 
-		indices = null;
-
-		if ( indexedGeometry ) {
+		const values = copyFromBuffer( buffer, arrayType, pos, cardinality * valuesNumber, bigEndian );
 
-			indices = copyFromBuffer(
-				buffer,
-				indicesType === 1 ? Uint32Array : Uint16Array,
-				pos,
-				indicesNumber,
-				bigEndian
-			);
+		pos += arrayType.BYTES_PER_ELEMENT * cardinality * valuesNumber;
 
-		}
-
-		return {
-			version: version,
-			attributes: attributes,
-			indices: indices
+		attributes[ attributeName ] = {
+			type: attributeType,
+			cardinality: cardinality,
+			values: values
 		};
 
 	}
 
-	// Define the public interface
+	pos = Math.ceil( pos / 4 ) * 4;
+
+	let indices = null;
 
-	function PRWMLoader( manager ) {
+	if ( indexedGeometry ) {
 
-		Loader.call( this, manager );
+		indices = copyFromBuffer(
+			buffer,
+			indicesType === 1 ? Uint32Array : Uint16Array,
+			pos,
+			indicesNumber,
+			bigEndian
+		);
 
 	}
 
-	PRWMLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
+	return {
+		version: version,
+		attributes: attributes,
+		indices: indices
+	};
+
+}
+
+// Define the public interface
 
-		constructor: PRWMLoader,
+class PRWMLoader extends Loader {
 
-		load: function ( url, onLoad, onProgress, onError ) {
+	constructor( manager ) {
 
-			var scope = this;
+		super( manager );
+
+	}
 
-			var loader = new FileLoader( scope.manager );
-			loader.setPath( scope.path );
-			loader.setResponseType( 'arraybuffer' );
-			loader.setRequestHeader( scope.requestHeader );
-			loader.setWithCredentials( scope.withCredentials );
+	load( url, onLoad, onProgress, onError ) {
 
-			url = url.replace( /\*/g, isBigEndianPlatform() ? 'be' : 'le' );
+		const scope = this;
 
-			loader.load( url, function ( arrayBuffer ) {
+		const loader = new FileLoader( scope.manager );
+		loader.setPath( scope.path );
+		loader.setResponseType( 'arraybuffer' );
+		loader.setRequestHeader( scope.requestHeader );
+		loader.setWithCredentials( scope.withCredentials );
 
-				try {
+		url = url.replace( /\*/g, isBigEndianPlatform() ? 'be' : 'le' );
 
-					onLoad( scope.parse( arrayBuffer ) );
+		loader.load( url, function ( arrayBuffer ) {
 
-				} catch ( e ) {
+			try {
 
-					if ( onError ) {
+				onLoad( scope.parse( arrayBuffer ) );
 
-						onError( e );
+			} catch ( e ) {
 
-					} else {
+				if ( onError ) {
 
-						console.error( e );
+					onError( e );
 
-					}
+				} else {
 
-					scope.manager.itemError( url );
+					console.error( e );
 
 				}
 
-			}, onProgress, onError );
+				scope.manager.itemError( url );
 
-		},
+			}
 
-		parse: function ( arrayBuffer ) {
+		}, onProgress, onError );
 
-			var data = decodePrwm( arrayBuffer ),
-				attributesKey = Object.keys( data.attributes ),
-				bufferGeometry = new BufferGeometry(),
-				attribute,
-				i;
+	}
 
-			for ( i = 0; i < attributesKey.length; i ++ ) {
+	parse( arrayBuffer ) {
 
-				attribute = data.attributes[ attributesKey[ i ] ];
-				bufferGeometry.setAttribute( attributesKey[ i ], new BufferAttribute( attribute.values, attribute.cardinality, attribute.normalized ) );
+		const data = decodePrwm( arrayBuffer ),
+			attributesKey = Object.keys( data.attributes ),
+			bufferGeometry = new BufferGeometry();
 
-			}
+		for ( let i = 0; i < attributesKey.length; i ++ ) {
 
-			if ( data.indices !== null ) {
+			const attribute = data.attributes[ attributesKey[ i ] ];
+			bufferGeometry.setAttribute( attributesKey[ i ], new BufferAttribute( attribute.values, attribute.cardinality, attribute.normalized ) );
 
-				bufferGeometry.setIndex( new BufferAttribute( data.indices, 1 ) );
+		}
 
-			}
+		if ( data.indices !== null ) {
 
-			return bufferGeometry;
+			bufferGeometry.setIndex( new BufferAttribute( data.indices, 1 ) );
 
 		}
 
-	} );
+		return bufferGeometry;
 
-	PRWMLoader.isBigEndianPlatform = function () {
+	}
 
-		return isBigEndianPlatform();
+	static isBigEndianPlatform() {
 
-	};
+		return isBigEndianPlatform();
 
-	return PRWMLoader;
+	}
 
-} )();
+}
 
 export { PRWMLoader };

文件差異過大導致無法顯示
+ 491 - 510
examples/jsm/loaders/SVGLoader.js


部分文件因文件數量過多而無法顯示