Explorar el Código

Merge pull request #13156 from kaisalmen/OBJLoader2_V230

OBJLoader2 V2.3.1: Parser Verification, Point and Line support, moved generic functions to LoaderBase
Mr.doob hace 7 años
padre
commit
827e3e16c5

+ 34 - 7
docs/examples/loaders/LoaderSupport.html

@@ -158,7 +158,7 @@
 
 		<h3>[method:null validate] ( [page:Function functionCodeBuilder], Array of [page:String libLocations], [page:String libPath], [page:LoaderSupport.WorkerRunnerRefImpl runnerImpl] )</h3>
 		<div>
-			[page:Function functionCodeBuilder] - Function that is invoked with funcBuildObject and funcBuildSingelton that allows stringification of objects and singletons.<br>
+			[page:Function functionCodeBuilder] - Function that is invoked with funcBuildObject and funcBuildSingleton that allows stringification of objects and singletons.<br>
 			Array of [page:String libLocations] - URL of libraries that shall be added to worker code relative to libPath.<br>
 			[page:String libPath] - Base path used for loading libraries.<br>
 			[page:LoaderSupport.WorkerRunnerRefImpl runnerImpl] - The default worker parser wrapper implementation (communication and execution). An extended class could be passed here.
@@ -405,12 +405,35 @@
 			[page:LoaderSupport.ConsoleLogger logger] - logger to be used
 		</div>
 		<div>
-			Base class to be used by loaders.
+			Base class to be used by Loaders that provide load, parse, parseAsync and run
 		</div>
 
 
 		<h2>Methods</h2>
-
+		
+		<h3>[method:null load]( [page:String url], [page:Function onLoad], [page:Function onProgress], [page:Function onError], [page:Function onMeshAlter], [page:boolean useAsync] )</h3>
+		<div>
+			[page:String url] - A string containing the path/URL of the file to be loaded.<br>
+			[page:Function onLoad] - A function to be called after loading is successfully completed. The function receives loaded [page:Object3D] as an argument.<br>
+			[page:Function onProgress] - (optional) A function to be called while the loading is in progress. The argument will be the XMLHttpRequest instance, which contains [page:Integer total] and [page:Integer loaded] bytes.<br>
+			[page:Function onError] - (optional) A function to be called if an error occurs during loading. The function receives the error as an argument.<br>
+			[page:Function onMeshAlter] - (optional) A function to be called after a new mesh raw data becomes available for alteration.<br>
+			[page:boolean useAsync] - (optional) If true, uses async loading with worker, if false loads data synchronously.
+		</div>
+		<div>
+			Use this convenient method to load a file at the given URL. By default the fileLoader uses an ArrayBuffer.
+		</div>
+		
+		<h3>[method:ConsoleLogger checkResourceDescriptorFiles] ( [page:THREE.LoaderSupport.ResourceDescriptor resources], [page:Object fileDesc] )</h3>
+		<div>
+			[page:THREE.LoaderSupport.ResourceDescriptor resources] - Array of {@link THREE.LoaderSupport.ResourceDescriptor}
+			[page:Object fileDesc] - Object describing which resources are of interest (ext, type (string or UInt8Array) and ignore (boolean))
+		</div>
+		<div>
+			Identify files or content of interest from an Array of {@link THREE.LoaderSupport.ResourceDescriptor}. Returns Object with each "ext" and the corresponding {@link THREE.LoaderSupport.ResourceDescriptor}
+	 	</div>
+		
+		
 		<h3>[method:ConsoleLogger getLogger] ()</h3>
 		<div>
 			Returns [page:LoaderSupport.ConsoleLogger].
@@ -608,36 +631,40 @@
 		</div>
 
 
-		<h3>[method:null logDebug]( [page:String message] )</h3>
+		<h3>[method:null logDebug]( [page:String message], Array of [page:String additional] )</h3>
 		<div>
 			[page:String message] - Message to log
+			Array of [page:String additional] - Array of [page:String strings] containing additional content to be logged
 		</div>
 		<div>
 			Log a debug message if enabled and debug is set.
 		</div>
 
 
-		<h3>[method:null logInfo]( [page:String message] )</h3>
+		<h3>[method:null logInfo]( [page:String message], Array of [page:String additional] )</h3>
 		<div>
 			[page:String message] - Message to log
+			Array of [page:String additional] - Array of [page:String strings] containing additional content to be logged
 		</div>
 		<div>
 			Log an info message if enabled.
 		</div>
 
 
-		<h3>[method:null logWarn]( [page:String message] )</h3>
+		<h3>[method:null logWarn]( [page:String message], Array of [page:String additional] )</h3>
 		<div>
 			[page:String message] - Message to log
+			Array of [page:String additional] - Array of [page:String strings] containing additional content to be logged
 		</div>
 		<div>
 			Log a warn message (always).
 		</div>
 
 
-		<h3>[method:null logError]( [page:String message] )</h3>
+		<h3>[method:null logError]( [page:String message], Array of [page:String additional] )</h3>
 		<div>
 			[page:String message] - Message to log
+			Array of [page:String additional] - Array of [page:String strings] containing additional content to be logged
 		</div>
 		<div>
 			Log an error message (always).

+ 22 - 16
docs/examples/loaders/OBJLoader2.html

@@ -11,7 +11,7 @@
 
 		<h1>[name]</h1>
 
-		<div class="desc">A loader for loading a <em>.obj</em> resource. <br />
+		<div class="desc">A loader for loading a <em>.obj</em> resource.<br />
 			The <a href="https://en.wikipedia.org/wiki/Wavefront_.obj_file">OBJ file format</a> is a simple data-format
 			that represents 3D geometry in a human redeable format as, the position of each vertex, the UV position of
 			each texture coordinate vertex, vertex normals, and the faces that make each polygon defined as a list of
@@ -42,7 +42,7 @@
 
 		<h3>[name]( [page:LoadingManager manager], [page:LoaderSupport.ConsoleLogger logger] )</h3>
 		<div>
-			[page:LoadingManager manager] - The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].
+			[page:LoadingManager manager] - The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].<br>
 			[page:LoaderSupport.ConsoleLogger logger] - logger to be used
 		</div>
 		<div>
@@ -71,19 +71,8 @@
 		</div>
 
 
-		<h3>[method:null load]( [page:String url], [page:Function onLoad], [page:Function onProgress], [page:Function onError], [page:Function onMeshAlter], [page:boolean useAsync] )</h3>
-		<div>
-			[page:String url] - A string containing the path/URL of the <em>.obj</em> file.<br>
-			[page:Function onLoad] - A function to be called after loading is successfully completed. The function receives loaded [page:Object3D] as an argument.<br>
-			[page:Function onProgress] - (optional) A function to be called while the loading is in progress. The argument will be the XMLHttpRequest instance, which contains [page:Integer total] and [page:Integer loaded] bytes.<br>
-			[page:Function onError] - (optional) A function to be called if an error occurs during loading. The function receives the error as an argument.<br>
-			[page:Function onMeshAlter] - (optional) A function to be called after a new mesh raw data becomes available for alteration.<br>
-			[page:boolean useAsync] - (optional) If true, uses async loading with worker, if false loads data synchronously.
-		</div>
-		<div>
-			Use this convenient method to load an OBJ file at the given URL. By default the fileLoader uses an arraybuffer.
-		</div>
-
+		<h3>[method:null load] => [page:LoaderSupport.LoaderBase.load]</h3>
+		
 
 		<h3>[method:null run]( [page:LoaderSupport.PrepData params], [page:LoaderSupport.WorkerSupport workerSupportExternal] )</h3>
 		<div>
@@ -94,7 +83,10 @@
 			Run the loader according the provided instructions.
 		</div>
 
-
+		
+		<h3>[method:Object checkResourceDescriptorFiles] => [page:LoaderSupport.LoaderBase.checkResourceDescriptorFiles]</h3>
+		
+		
 		<h3>[method:null setMaterialPerSmoothingGroup] ( [page:boolean materialPerSmoothingGroup] )</h3>
 		<div>
 			[page:boolean materialPerSmoothingGroup]
@@ -164,7 +156,21 @@
 		<div>
 			Tells whether normals should be completely disregarded and regenerated.
 		</div>
+		
+		
+		<h3>[method:null loadMtl]( [page:String url], [page:Object content], [page:Function callbackOnLoad], [page:String crossOrigin], [page:Object materialOptions]) </h3>
+		<div>
+			[page:String url] - URL to the file
+			[page:Object content] - The file content as arraybuffer or text
+			[page:Function callbackOnLoad] - Callback to be called after successful load
+			[page:String crossOrigin] - (optional) CORS value
+			[page:Function materialOptions] - (optional) Set material loading options for MTLLoader
+		</div>
+		<div>
+			Utility method for loading an mtl file according resource description. Provide url or content..
+		</div>
 
+		
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/OBJLoader2.js examples/js/loaders/OBJLoader2.js]

+ 271 - 63
examples/js/loaders/LoaderSupport.js

@@ -93,9 +93,15 @@ THREE.LoaderSupport.ConsoleLogger = (function () {
 	 * @memberOf THREE.LoaderSupport.ConsoleLogger
 	 *
 	 * @param {string} message Message to log
+	 * @param {string[]} additional Array of strings containing additional content to be logged
+	 *
 	 */
-	ConsoleLogger.prototype.logDebug = function ( message ) {
-		if ( this.enabled && this.debug ) console.info( message );
+	ConsoleLogger.prototype.logDebug = function ( message, additional ) {
+		if ( this.enabled && this.debug ) {
+
+			this._createStatement( message, 'Additional content:', additional, function ( output ) { console.debug( output ) } );
+
+		}
 	};
 
 	/**
@@ -103,9 +109,14 @@ THREE.LoaderSupport.ConsoleLogger = (function () {
 	 * @memberOf THREE.LoaderSupport.ConsoleLogger
 	 *
 	 * @param {string} message Message to log
+	 * @param {string[]} additional Array of strings containing additional content to be logged
 	 */
-	ConsoleLogger.prototype.logInfo = function ( message ) {
-		if ( this.enabled ) console.info( message );
+	ConsoleLogger.prototype.logInfo = function ( message, additional ) {
+		if ( this.enabled ) {
+
+			this._createStatement( message, 'Additional content:', additional, function ( output ) { console.info( output ) } );
+
+		}
 	};
 
 	/**
@@ -113,9 +124,10 @@ THREE.LoaderSupport.ConsoleLogger = (function () {
 	 * @memberOf THREE.LoaderSupport.ConsoleLogger
 	 *
 	 * @param {string} message Message to log
+	 * @param {string[]} additional Array of strings containing additional content to be logged
 	 */
-	ConsoleLogger.prototype.logWarn = function ( message ) {
-		console.warn( message );
+	ConsoleLogger.prototype.logWarn = function ( message, additional ) {
+		this._createStatement( message, 'Additional content:', additional, function ( output ) { console.warn( output ) } );
 	};
 
 	/**
@@ -123,9 +135,10 @@ THREE.LoaderSupport.ConsoleLogger = (function () {
 	 * @memberOf THREE.LoaderSupport.ConsoleLogger
 	 *
 	 * @param {string} message Message to log
+	 * @param {string[]} additional Array of strings containing additional content to be logged
 	 */
-	ConsoleLogger.prototype.logError = function ( message ) {
-		console.error( message );
+	ConsoleLogger.prototype.logError = function ( message, additional ) {
+		this._createStatement( message, 'Additional content:', additional, function ( output ) { console.error( output ) } );
 	};
 
 	/**
@@ -148,6 +161,16 @@ THREE.LoaderSupport.ConsoleLogger = (function () {
 		if ( this.enabled ) console.timeEnd( id );
 	};
 
+	ConsoleLogger.prototype._createStatement = function ( message, addHeader, additional, logFunction ) {
+		var output = message;
+		if ( Array.isArray( additional ) ) {
+
+			output += '\n' + addHeader + '\n' + additional.join( '\n' );
+
+		}
+		logFunction( output );
+	};
+
 	return ConsoleLogger;
 })();
 
@@ -445,8 +468,41 @@ THREE.LoaderSupport.Builder = (function () {
 		this.logger.logInfo( 'Using THREE.LoaderSupport.Builder version: ' + LOADER_BUILDER_VERSION );
 		this.callbacks = new THREE.LoaderSupport.Callbacks();
 		this.materials = [];
+		this._createDefaultMaterials();
 	}
 
+	Builder.prototype._createDefaultMaterials = function () {
+		var defaultMaterial = new THREE.MeshStandardMaterial( { color: 0xDCF1FF } );
+		defaultMaterial.name = 'defaultMaterial';
+
+		var defaultVertexColorMaterial = new THREE.MeshStandardMaterial( { color: 0xDCF1FF } );
+		defaultVertexColorMaterial.name = 'defaultVertexColorMaterial';
+		defaultVertexColorMaterial.vertexColors = THREE.VertexColors;
+
+		var defaultLineMaterial = new THREE.LineBasicMaterial();
+		defaultLineMaterial.name = 'defaultLineMaterial';
+
+		var defaultPointMaterial = new THREE.PointsMaterial( { size: 1, sizeAttenuation: false } );
+		defaultPointMaterial.name = 'defaultPointMaterial';
+
+		var runtimeMaterials = {};
+		runtimeMaterials[ defaultMaterial.name ] = defaultMaterial;
+		runtimeMaterials[ defaultVertexColorMaterial.name ] = defaultVertexColorMaterial;
+		runtimeMaterials[ defaultLineMaterial.name ] = defaultLineMaterial;
+		runtimeMaterials[ defaultPointMaterial.name ] = defaultPointMaterial;
+
+		this.updateMaterials(
+			{
+				cmd: 'materialData',
+				materials: {
+					materialCloneInstructions: null,
+					serializedMaterials: null,
+					runtimeMaterials: runtimeMaterials
+				}
+			}
+		);
+	};
+
 	/**
 	 * Set materials loaded by any supplier of an Array of {@link THREE.Material}.
 	 * @memberOf THREE.LoaderSupport.Builder
@@ -560,6 +616,7 @@ THREE.LoaderSupport.Builder = (function () {
 		var callbackOnMeshAlter = this.callbacks.onMeshAlter;
 		var callbackOnMeshAlterResult;
 		var useOrgMesh = true;
+		var geometryType = Validator.verifyInput( meshPayload.geometryType, 0 );
 		if ( Validator.isValid( callbackOnMeshAlter ) ) {
 
 			callbackOnMeshAlterResult = callbackOnMeshAlter(
@@ -567,7 +624,8 @@ THREE.LoaderSupport.Builder = (function () {
 					detail: {
 						meshName: meshName,
 						bufferGeometry: bufferGeometry,
-						material: material
+						material: material,
+						geometryType: geometryType
 					}
 				}
 			);
@@ -589,7 +647,20 @@ THREE.LoaderSupport.Builder = (function () {
 		}
 		if ( useOrgMesh ) {
 
-			mesh = new THREE.Mesh( bufferGeometry, material );
+			if ( meshPayload.computeBoundingSphere ) bufferGeometry.computeBoundingSphere();
+			if ( geometryType === 0 ) {
+
+				mesh = new THREE.Mesh( bufferGeometry, material );
+
+			} else if ( geometryType === 1) {
+
+				mesh = new THREE.LineSegments( bufferGeometry, material );
+
+			} else {
+
+				mesh = new THREE.Points( bufferGeometry, material );
+
+			}
 			mesh.name = meshName;
 			meshes.push( mesh );
 
@@ -645,19 +716,27 @@ THREE.LoaderSupport.Builder = (function () {
 
 			var materialNameOrg = materialCloneInstructions.materialNameOrg;
 			var materialOrg = this.materials[ materialNameOrg ];
-			material = materialOrg.clone();
 
-			materialName = materialCloneInstructions.materialName;
-			material.name = materialName;
+			if ( Validator.isValid( materialNameOrg ) ) {
 
-			var materialProperties = materialCloneInstructions.materialProperties;
-			for ( var key in materialProperties ) {
+				material = materialOrg.clone();
 
-				if ( material.hasOwnProperty( key ) && materialProperties.hasOwnProperty( key ) ) material[ key ] = materialProperties[ key ];
+				materialName = materialCloneInstructions.materialName;
+				material.name = materialName;
 
-			}
-			this.materials[ materialName ] = material;
+				var materialProperties = materialCloneInstructions.materialProperties;
+				for ( var key in materialProperties ) {
+
+					if ( material.hasOwnProperty( key ) && materialProperties.hasOwnProperty( key ) ) material[ key ] = materialProperties[ key ];
+
+				}
+				this.materials[ materialName ] = material;
+
+			} else {
+
+				this.logger.logWarn( 'Requested material "' + materialNameOrg + '" is not available!' );
 
+			}
 		}
 
 		var materials = materialPayload.materials.serializedMaterials;
@@ -723,7 +802,7 @@ THREE.LoaderSupport.Builder = (function () {
 })();
 
 /**
- * Base class to be used by loaders.
+ * Base class to be used by Loaders that provide load, parse, parseAsync and run
  * @class
  *
  * @param {THREE.DefaultLoadingManager} [manager] The loadingManager for the loader to use. Default is {@link THREE.DefaultLoadingManager}
@@ -738,6 +817,9 @@ THREE.LoaderSupport.LoaderBase = (function () {
 		this.manager = Validator.verifyInput( manager, THREE.DefaultLoadingManager );
 		this.logger = Validator.verifyInput( logger, new ConsoleLogger() );
 
+		this.fileLoader = new THREE.FileLoader( this.manager );
+		this.fileLoader.setResponseType( 'arraybuffer' );
+
 		this.modelName = '';
 		this.instanceNo = 0;
 		this.path = '';
@@ -746,33 +828,8 @@ THREE.LoaderSupport.LoaderBase = (function () {
 
 		this.loaderRootNode = new THREE.Group();
 		this.builder = new THREE.LoaderSupport.Builder( this.logger );
-		this._createDefaultMaterials();
 		this.callbacks = new THREE.LoaderSupport.Callbacks();
-	};
-
-	LoaderBase.prototype._createDefaultMaterials = function () {
-		var defaultMaterial = new THREE.MeshStandardMaterial( { color: 0xDCF1FF } );
-		defaultMaterial.name = 'defaultMaterial';
-
-		var vertexColorMaterial = new THREE.MeshStandardMaterial( { color: 0xDCF1FF } );
-		vertexColorMaterial.name = 'vertexColorMaterial';
-		vertexColorMaterial.vertexColors = THREE.VertexColors;
-
-		var runtimeMaterials = {};
-		runtimeMaterials[ defaultMaterial.name ] = defaultMaterial;
-		runtimeMaterials[ vertexColorMaterial.name ] = vertexColorMaterial;
-
-		this.builder.updateMaterials(
-			{
-				cmd: 'materialData',
-				materials: {
-					materialCloneInstructions: null,
-					serializedMaterials: null,
-					runtimeMaterials: runtimeMaterials
-				}
-			}
-		);
-	};
+	}
 
 	LoaderBase.prototype._applyPrepData = function ( prepData ) {
 		if ( Validator.isValid( prepData ) ) {
@@ -891,6 +948,141 @@ THREE.LoaderSupport.LoaderBase = (function () {
 		this.logger.logDebug( content );
 	};
 
+	/**
+	 * Use this convenient method to load a file at the given URL. By default the fileLoader uses an ArrayBuffer.
+	 * @memberOf THREE.LoaderSupport.LoaderBase
+	 *
+	 * @param {string}  url A string containing the path/URL of the file to be loaded.
+	 * @param {callback} onLoad A function to be called after loading is successfully completed. The function receives loaded Object3D as an argument.
+	 * @param {callback} [onProgress] A function to be called while the loading is in progress. The argument will be the XMLHttpRequest instance, which contains total and Integer bytes.
+	 * @param {callback} [onError] A function to be called if an error occurs during loading. The function receives the error as an argument.
+	 * @param {callback} [onMeshAlter] A function to be called after a new mesh raw data becomes available for alteration.
+	 * @param {boolean} [useAsync] If true, uses async loading with worker, if false loads data synchronously.
+	 */
+	LoaderBase.prototype.load = function ( url, onLoad, onProgress, onError, onMeshAlter, useAsync ) {
+		var scope = this;
+		if ( ! Validator.isValid( onProgress ) ) {
+			var numericalValueRef = 0;
+			var numericalValue = 0;
+			onProgress = function ( event ) {
+				if ( ! event.lengthComputable ) return;
+
+				numericalValue = event.loaded / event.total;
+				if ( numericalValue > numericalValueRef ) {
+
+					numericalValueRef = numericalValue;
+					var output = 'Download of "' + url + '": ' + ( numericalValue * 100 ).toFixed( 2 ) + '%';
+					scope.onProgress( 'progressLoad', output, numericalValue );
+
+				}
+			};
+		}
+
+		if ( ! Validator.isValid( onError ) ) {
+			onError = function ( event ) {
+				var output = 'Error occurred while downloading "' + url + '"';
+				scope.logger.logError( output + ': ' + event );
+				scope.onProgress( 'error', output, -1 );
+			};
+		}
+
+		this.fileLoader.setPath( this.path );
+		this.fileLoader.load( url, function ( content ) {
+			if ( useAsync ) {
+
+				scope.parseAsync( content, onLoad );
+
+			} else {
+
+				var callbacks = new THREE.LoaderSupport.Callbacks();
+				callbacks.setCallbackOnMeshAlter( onMeshAlter );
+				scope._setCallbacks( callbacks );
+				onLoad(
+					{
+						detail: {
+							loaderRootNode: scope.parse( content ),
+							modelName: scope.modelName,
+							instanceNo: scope.instanceNo
+						}
+					}
+				);
+
+			}
+
+		}, onProgress, onError );
+
+	};
+
+	/**
+	 * Identify files or content of interest from an Array of {@link THREE.LoaderSupport.ResourceDescriptor}.
+	 *
+	 * @param {THREE.LoaderSupport.ResourceDescriptor[]} resources Array of {@link THREE.LoaderSupport.ResourceDescriptor}
+	 * @param Object fileDesc Object describing which resources are of interest (ext, type (string or UInt8Array) and ignore (boolean))
+	 * @returns {{}} Object with each "ext" and the corresponding {@link THREE.LoaderSupport.ResourceDescriptor}
+	 */
+	LoaderBase.prototype.checkResourceDescriptorFiles = function ( resources, fileDesc ) {
+		var resource, triple, i, found;
+		var result = {};
+
+		for ( var index in resources ) {
+
+			resource = resources[ index ];
+			found = false;
+			if ( ! Validator.isValid( resource.name ) ) continue;
+			if ( Validator.isValid( resource.content ) ) {
+
+				for ( i = 0; i < fileDesc.length && !found; i++ ) {
+
+					triple = fileDesc[ i ];
+					if ( resource.extension.toLowerCase() === triple.ext.toLowerCase() ) {
+
+						if ( triple.ignore ) {
+
+							found = true;
+
+						} else if ( triple.type === "Uint8Array" ) {
+
+							// fast-fail on bad type
+							if ( ! ( resource.content instanceof Uint8Array ) ) throw 'Provided content is not of type arraybuffer! Aborting...';
+							result[ triple.ext ] = resource;
+							found = true;
+
+						} else if ( triple.type === "String" ) {
+
+							if ( ! (typeof(resource.content) === 'string' || resource.content instanceof String) ) throw 'Provided  content is not of type String! Aborting...';
+							result[ triple.ext ] = resource;
+							found = true;
+
+						}
+
+					}
+
+				}
+				if ( !found ) throw 'Unidentified resource "' + resource.name + '": ' + resource.url;
+
+			} else {
+
+				// fast-fail on bad type
+				if ( ! ( typeof( resource.name ) === 'string' || resource.name instanceof String ) ) throw 'Provided file is not properly defined! Aborting...';
+				for ( i = 0; i < fileDesc.length && !found; i++ ) {
+
+					triple = fileDesc[ i ];
+					if ( resource.extension.toLowerCase() === triple.ext.toLowerCase() ) {
+
+						if ( ! triple.ignore ) result[ triple.ext ] = resource;
+						found = true;
+
+					}
+
+				}
+				if ( !found ) throw 'Unidentified resource "' + resource.name + '": ' + resource.url;
+
+			}
+		}
+
+		return result;
+	};
+
 	return LoaderBase;
 })();
 
@@ -989,7 +1181,7 @@ THREE.LoaderSupport.WorkerRunnerRefImpl = (function () {
  */
 THREE.LoaderSupport.WorkerSupport = (function () {
 
-	var WORKER_SUPPORT_VERSION = '2.0.1';
+	var WORKER_SUPPORT_VERSION = '2.1.2';
 
 	var Validator = THREE.LoaderSupport.Validator;
 
@@ -1158,12 +1350,13 @@ THREE.LoaderSupport.WorkerSupport = (function () {
 	 * Validate the status of worker code and the derived worker.
 	 * @memberOf THREE.LoaderSupport.WorkerSupport
 	 *
-	 * @param {Function} functionCodeBuilder Function that is invoked with funcBuildObject and funcBuildSingelton that allows stringification of objects and singletons.
+	 * @param {Function} functionCodeBuilder Function that is invoked with funcBuildObject and funcBuildSingleton that allows stringification of objects and singletons.
+	 * @param {String} parserName Name of the Parser object
 	 * @param {String[]} libLocations URL of libraries that shall be added to worker code relative to libPath
 	 * @param {String} libPath Base path used for loading libraries
 	 * @param {THREE.LoaderSupport.WorkerRunnerRefImpl} runnerImpl The default worker parser wrapper implementation (communication and execution). An extended class could be passed here.
 	 */
-	WorkerSupport.prototype.validate = function ( functionCodeBuilder, libLocations, libPath, runnerImpl ) {
+	WorkerSupport.prototype.validate = function ( functionCodeBuilder, parserName, libLocations, libPath, runnerImpl ) {
 		if ( Validator.isValid( this.loaderWorker.worker ) ) return;
 
 		this.logger.logInfo( 'WorkerSupport: Building worker code...' );
@@ -1171,17 +1364,18 @@ THREE.LoaderSupport.WorkerSupport = (function () {
 
 		if ( Validator.isValid( runnerImpl ) ) {
 
-			this.logger.logInfo( 'WorkerSupport: Using "' + runnerImpl.name + '" as Runncer class for worker.' );
+			this.logger.logInfo( 'WorkerSupport: Using "' + runnerImpl.name + '" as Runner class for worker.' );
 
 		} else {
 
 			runnerImpl = THREE.LoaderSupport.WorkerRunnerRefImpl;
-			this.logger.logInfo( 'WorkerSupport: Using DEFAULT "THREE.LoaderSupport.WorkerRunnerRefImpl" as Runncer class for worker.' );
+			this.logger.logInfo( 'WorkerSupport: Using DEFAULT "THREE.LoaderSupport.WorkerRunnerRefImpl" as Runner class for worker.' );
 
 		}
 
-		var userWorkerCode = functionCodeBuilder( buildObject, buildSingelton );
-		userWorkerCode += buildSingelton( runnerImpl.name, runnerImpl.name, runnerImpl );
+		var userWorkerCode = functionCodeBuilder( buildObject, buildSingleton );
+		userWorkerCode += 'var Parser = '+ parserName + ';\n\n';
+		userWorkerCode += buildSingleton( runnerImpl.name, runnerImpl );
 		userWorkerCode += 'new ' + runnerImpl.name + '();\n\n';
 
 		var scope = this;
@@ -1191,7 +1385,7 @@ THREE.LoaderSupport.WorkerSupport = (function () {
 			var loadAllLibraries = function ( path, locations ) {
 				if ( locations.length === 0 ) {
 
-					scope.loaderWorker.initWorker( libsContent + userWorkerCode, scope.logger, runnerImpl.name );
+					scope.loaderWorker.initWorker( libsContent + userWorkerCode, runnerImpl.name );
 					scope.logger.logTimeEnd( 'buildWebWorkerCode' );
 
 				} else {
@@ -1213,7 +1407,7 @@ THREE.LoaderSupport.WorkerSupport = (function () {
 
 		} else {
 
-			this.loaderWorker.initWorker( userWorkerCode, this.logger, runnerImpl.name );
+			this.loaderWorker.initWorker( userWorkerCode, runnerImpl.name );
 			this.logger.logTimeEnd( 'buildWebWorkerCode' );
 
 		}
@@ -1282,27 +1476,41 @@ THREE.LoaderSupport.WorkerSupport = (function () {
 		return objectString;
 	};
 
-	var buildSingelton = function ( fullName, internalName, object ) {
-		var objectString = fullName + ' = (function () {\n\n';
-		objectString += '\t' + object.prototype.constructor.toString() + '\n\n';
-		objectString = objectString.replace( object.name, internalName );
+	var buildSingleton = function ( fullName, object, internalName ) {
+		var objectString = '';
+		var objectName = ( Validator.isValid( internalName ) ) ? internalName : object.name;
 
-		var funcString;
-		var objectPart;
+		var funcString, objectPart, constructorString;
 		for ( var name in object.prototype ) {
 
 			objectPart = object.prototype[ name ];
-			if ( typeof objectPart === 'function' ) {
+			if ( name === 'constructor' ) {
 
 				funcString = objectPart.toString();
-				objectString += '\t' + internalName + '.prototype.' + name + ' = ' + funcString + ';\n\n';
+				funcString = funcString.replace( 'function', '' );
+				constructorString = '\tfunction ' + objectName + funcString + ';\n\n';
+
+			} else if ( typeof objectPart === 'function' ) {
+
+				funcString = objectPart.toString();
+				objectString += '\t' + objectName + '.prototype.' + name + ' = ' + funcString + ';\n\n';
 
 			}
 
 		}
-		objectString += '\treturn ' + internalName + ';\n';
+		objectString += '\treturn ' + objectName + ';\n';
 		objectString += '})();\n\n';
+		if ( ! Validator.isValid( constructorString ) ) {
+
+			constructorString = fullName + ' = (function () {\n\n';
+			constructorString += '\t' + object.prototype.constructor.toString() + '\n\n';
+			objectString = constructorString + objectString;
 
+		} else {
+
+			objectString = fullName + ' = (function () {\n\n' + constructorString + objectString;
+
+		}
 		return objectString;
 	};
 

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 219 - 517
examples/js/loaders/OBJLoader2.js


+ 258 - 0
examples/models/obj/verify/gulpfile.js

@@ -0,0 +1,258 @@
+
+'use strict';
+
+var fs = require( 'fs' );
+
+var gulp = require( 'gulp' );
+var gutil = require( 'gulp-util' );
+
+
+var obj_verify = {
+	vertices: [],
+	normals: [],
+	uvs: [],
+	facesV: [],
+	facesVn: [],
+	facesVt: [],
+	materials: []
+};
+
+obj_verify.vertices.push( [ -1,  1,  1 ] );
+obj_verify.vertices.push( [ -1, -1,  1 ] );
+obj_verify.vertices.push( [  1, -1,  1 ] );
+obj_verify.vertices.push( [  1,  1,  1 ] );
+obj_verify.vertices.push( [ -1,  1, -1 ] );
+obj_verify.vertices.push( [ -1, -1, -1 ] );
+obj_verify.vertices.push( [  1, -1, -1 ] );
+obj_verify.vertices.push( [  1,  1, -1 ] );
+
+obj_verify.normals.push( [  0,  0,  1 ] );
+obj_verify.normals.push( [  0,  0, -1 ] );
+obj_verify.normals.push( [  0,  1,  0 ] );
+obj_verify.normals.push( [  0, -1,  0 ] );
+obj_verify.normals.push( [  1,  0,  0 ] );
+obj_verify.normals.push( [ -1,  0,  0 ] );
+
+obj_verify.uvs.push( [ 0, 1 ] );
+obj_verify.uvs.push( [ 1, 1 ] );
+obj_verify.uvs.push( [ 1, 0 ] );
+obj_verify.uvs.push( [ 0, 0 ] );
+
+obj_verify.facesV.push( [ 1, 2, 3, 4 ] );
+obj_verify.facesV.push( [ 8, 7, 6, 5 ] );
+obj_verify.facesV.push( [ 4, 3, 7, 8 ] );
+obj_verify.facesV.push( [ 5, 1, 4, 8 ] );
+obj_verify.facesV.push( [ 5, 6, 2, 1 ] );
+obj_verify.facesV.push( [ 2, 6, 7, 3 ] );
+
+obj_verify.facesVn.push( [ 1, 1, 1, 1 ] );
+obj_verify.facesVn.push( [ 2, 2, 2, 2 ] );
+obj_verify.facesVn.push( [ 5, 5, 5, 5 ] );
+obj_verify.facesVn.push( [ 3, 3, 3, 3 ] );
+obj_verify.facesVn.push( [ 6, 6, 6, 6 ] );
+obj_verify.facesVn.push( [ 4, 4, 4, 4 ] );
+
+obj_verify.facesVt.push( [ 1, 2, 3, 4 ] );
+obj_verify.facesVt.push( [ 1, 2, 3, 4 ] );
+obj_verify.facesVt.push( [ 1, 2, 3, 4 ] );
+obj_verify.facesVt.push( [ 1, 2, 3, 4 ] );
+obj_verify.facesVt.push( [ 1, 2, 3, 4 ] );
+obj_verify.facesVt.push( [ 1, 2, 3, 4 ] );
+
+obj_verify.materials.push( 'usemtl red' );
+obj_verify.materials.push( 'usemtl blue' );
+obj_verify.materials.push( 'usemtl green' );
+obj_verify.materials.push( 'usemtl lightblue' );
+obj_verify.materials.push( 'usemtl orange' );
+obj_verify.materials.push( 'usemtl purple' );
+
+
+function vobjCreateVertices( factor, offsets ) {
+	var output = '\n';
+	for ( var x, y, z, i = 0, v = obj_verify.vertices, length = v.length; i < length; i++ ) {
+		x = v[ i ][ 0 ] * factor + offsets[ 0 ];
+		y = v[ i ][ 1 ] * factor + offsets[ 1 ];
+		z = v[ i ][ 2 ] * factor + offsets[ 2 ];
+		output += 'v ' + x + ' ' + y + ' ' + z + '\n';
+	}
+	return output;
+};
+
+function vobjCreateUvs() {
+	var output = '\n';
+	for ( var x, y, z, i = 0, vn = obj_verify.uvs, length = vn.length; i < length; i++ ) {
+		x = vn[ i ][ 0 ];
+		y = vn[ i ][ 1 ];
+		output += 'vt ' + x + ' ' + y + '\n';
+	}
+	return output;
+};
+
+function vobjCreateNormals() {
+	var output = '\n';
+	for ( var x, y, z, i = 0, vn = obj_verify.normals, length = vn.length; i < length; i++ ) {
+		x = vn[ i ][ 0 ];
+		y = vn[ i ][ 1 ];
+		z = vn[ i ][ 2 ];
+		output += 'vn ' + x + ' ' + y + ' ' + z + '\n';
+	}
+	return output;
+};
+
+function vobjCreateCubeV( offsets, groups, usemtls ) {
+	var output = '\n';
+	if ( groups === null || groups.length === 0 ) groups = [ null, null, null, null, null, null ];
+	if ( usemtls === null || usemtls.length === 0 ) usemtls = [ null, null, null, null, null, null ];
+	for ( var group, usemtl, f0, f1, f2, f3, i = 0, facesV = obj_verify.facesV, length = facesV.length; i < length; i++ ) {
+		f0 = facesV[ i ][ 0 ] + offsets[ 0 ];
+		f1 = facesV[ i ][ 1 ] + offsets[ 0 ];
+		f2 = facesV[ i ][ 2 ] + offsets[ 0 ];
+		f3 = facesV[ i ][ 3 ] + offsets[ 0 ];
+
+		group = groups[ i ];
+		usemtl = usemtls[ i ];
+		if ( group ) output += 'g ' + group + '\n';
+		if ( usemtl ) output += 'usemtl ' + usemtl + '\n';
+		output += 'f ' + f0 + ' ' + f1 + ' ' + f2 + ' ' + f3 + '\n';
+	}
+	return output;
+};
+
+function vobjCreateCubeVVn( offsets, groups, usemtls ) {
+	var output = '\n';
+	if ( groups === null || groups.length === 0 ) groups = [ null, null, null, null, null, null ];
+	if ( usemtls === null || usemtls.length === 0 ) usemtls = [ null, null, null, null, null, null ];
+	for ( var group, usemtl, f0, f1, f2, f3, i = 0, facesV = obj_verify.facesV, facesVn = obj_verify.facesVn; i < 6; i++ ) {
+
+		f0 = facesV[ i ][ 0 ] + offsets[ 0 ] + '//' + ( facesVn[ i ][ 0 ] + offsets[ 1 ] );
+		f1 = facesV[ i ][ 1 ] + offsets[ 0 ] + '//' + ( facesVn[ i ][ 1 ] + offsets[ 1 ] );
+		f2 = facesV[ i ][ 2 ] + offsets[ 0 ] + '//' + ( facesVn[ i ][ 2 ] + offsets[ 1 ] );
+		f3 = facesV[ i ][ 3 ] + offsets[ 0 ] + '//' + ( facesVn[ i ][ 3 ] + offsets[ 1 ] );
+
+		group = groups[ i ];
+		usemtl = usemtls[ i ];
+		if ( group ) output += 'g ' + group + '\n';
+		if ( usemtl ) output += 'usemtl ' + usemtl + '\n';
+		output += 'f ' + f0 + ' ' + f1 + ' ' + f2 + ' ' + f3 + '\n';
+
+	}
+	return output;
+};
+
+function vobjCreateCubeVVt( offsets, groups, usemtls ) {
+	var output = '\n';
+	if ( groups === null || groups.length === 0 ) groups = [ null, null, null, null, null, null ];
+	if ( usemtls === null || usemtls.length === 0 ) usemtls = [ null, null, null, null, null, null ];
+	for ( var group, usemtl, f0, f1, f2, f3, i = 0, facesV = obj_verify.facesV, facesVt = obj_verify.facesVt; i < 6; i++ ) {
+
+		f0 = facesV[ i ][ 0 ] + offsets[ 0 ] + '/' + ( facesVt[ i ][ 0 ] + offsets[ 1 ] );
+		f1 = facesV[ i ][ 1 ] + offsets[ 0 ] + '/' + ( facesVt[ i ][ 1 ] + offsets[ 1 ] );
+		f2 = facesV[ i ][ 2 ] + offsets[ 0 ] + '/' + ( facesVt[ i ][ 2 ] + offsets[ 1 ] );
+		f3 = facesV[ i ][ 3 ] + offsets[ 0 ] + '/' + ( facesVt[ i ][ 3 ] + offsets[ 1 ] );
+
+		group = groups[ i ];
+		usemtl = usemtls[ i ];
+		if ( group ) output += 'g ' + group + '\n';
+		if ( usemtl ) output += 'usemtl ' + usemtl + '\n';
+		output += 'f ' + f0 + ' ' + f1 + ' ' + f2 + ' ' + f3 + '\n';
+
+	}
+	return output;
+};
+
+function vobjCreateCubeVVnVt( offsets, groups, usemtls ) {
+	var output = '\n';
+	if ( groups === null || groups.length === 0 ) groups = [ null, null, null, null, null, null ];
+	if ( usemtls === null || usemtls.length === 0 ) usemtls = [ null, null, null, null, null, null ];
+	for ( var group, usemtl, f0, f1, f2, f3, i = 0, facesV = obj_verify.facesV, facesVt = obj_verify.facesVt, facesVn = obj_verify.facesVn; i < 6; i++ ) {
+
+		f0 = facesV[ i ][ 0 ] + offsets[ 0 ] + '/' + ( facesVt[ i ][ 0 ] + offsets[ 1 ] ) + '/' + ( facesVn[ i ][ 0 ] + offsets[ 2 ] );
+		f1 = facesV[ i ][ 1 ] + offsets[ 0 ] + '/' + ( facesVt[ i ][ 1 ] + offsets[ 1 ] ) + '/' + ( facesVn[ i ][ 1 ] + offsets[ 2 ] );
+		f2 = facesV[ i ][ 2 ] + offsets[ 0 ] + '/' + ( facesVt[ i ][ 2 ] + offsets[ 1 ] ) + '/' + ( facesVn[ i ][ 2 ] + offsets[ 2 ] );
+		f3 = facesV[ i ][ 3 ] + offsets[ 0 ] + '/' + ( facesVt[ i ][ 3 ] + offsets[ 1 ] ) + '/' + ( facesVn[ i ][ 3 ] + offsets[ 2 ] );
+
+		group = groups[ i ];
+		usemtl = usemtls[ i ];
+		if ( group ) output += 'g ' + group + '\n';
+		if ( usemtl ) output += 'usemtl ' + usemtl + '\n';
+		output += 'f ' + f0 + ' ' + f1 + ' ' + f2 + ' ' + f3 + '\n';
+
+	}
+	return output;
+};
+
+gulp.task( 'default', function( cb ){
+	gutil.log( 'Building: verify.obj' );
+	var offsets = [ 0, 0, 0 ];
+	var pos = [ -150, 50, 0 ];
+	fs.writeFileSync( './verify.obj', '# Verification OBJ created with gulp\n\n' );
+	fs.appendFileSync( './verify.obj', 'mtllib verify.mtl\n\n# Cube no materials. Translated x:' + pos[ 0 ] );
+	fs.appendFileSync( './verify.obj', vobjCreateVertices( 10, pos ) );
+	fs.appendFileSync( './verify.obj', vobjCreateCubeV( offsets, null, null ) );
+
+	pos[ 0 ] += 50;
+	offsets[ 0 ] += 8;
+	fs.appendFileSync( './verify.obj', '\n\n# Cube with two materials. Translated x:' + pos[ 0 ] );
+	fs.appendFileSync( './verify.obj', vobjCreateVertices( 10, pos ) );
+	fs.appendFileSync( './verify.obj', vobjCreateCubeV( offsets, null, [ 'orange', null, null, 'purple', null, null ] ) );
+
+	pos[ 0 ] += 50;
+	offsets[ 0 ] += 8;
+	fs.appendFileSync( './verify.obj', '\n\n# Cube with normals no materials. Translated x:' + pos[ 0 ] );
+	fs.appendFileSync( './verify.obj', vobjCreateVertices( 10, pos ) );
+	fs.appendFileSync( './verify.obj', vobjCreateNormals() );
+	fs.appendFileSync( './verify.obj', vobjCreateCubeVVn( offsets, [ 'cube3', null, null, null, null, null ], [ 'lightblue', null, null, null, null, null ] ) );
+
+	pos[ 0 ] += 50;
+	offsets[ 0 ] += 8;
+	fs.appendFileSync( './verify.obj', '\n\n# Cube with uvs and red material. Translated x:' + pos[ 0 ] );
+	fs.appendFileSync( './verify.obj', vobjCreateVertices( 10, pos ) );
+	fs.appendFileSync( './verify.obj', vobjCreateUvs() );
+	fs.appendFileSync( './verify.obj', vobjCreateCubeVVt( offsets, null, [ 'red', null, null, null, null, null ] ) );
+
+	pos[ 0 ] += 50;
+	offsets[ 0 ] += 8;
+	fs.appendFileSync( './verify.obj', '\n\n# cube with uvs and normals and material. Translated x' + pos[ 0 ] );
+	fs.appendFileSync( './verify.obj', vobjCreateVertices( 10, pos ) );
+
+	fs.appendFileSync( './verify.obj', vobjCreateCubeVVnVt( offsets, [], [ 'red', null, null, 'blue', null, 'green' ] ) );
+
+	pos[ 0 ] += 50;
+	offsets[ 0 ] += 8;
+	offsets[ 1 ] += 6;
+	fs.appendFileSync( './verify.obj', '\n\n# cube with uvs and normals and two materials and group for every quad. Translated x:' + pos[ 0 ] );
+	fs.appendFileSync( './verify.obj', vobjCreateVertices( 10, pos ) );
+	fs.appendFileSync( './verify.obj', vobjCreateNormals() );
+	fs.appendFileSync( './verify.obj', vobjCreateCubeVVnVt( [ -9, offsets[ 1 ], offsets[ 2 ] ],
+		[ 'cube6a', 'cube6b', 'cube6c', 'cube6d', 'cube6e', 'cube6f' ],
+		[ 'green', null, null, 'orange', null, null ] ) );
+
+	pos[ 0 ] += 50;
+	offsets[ 0 ] += 8;
+	fs.appendFileSync( './verify.obj', '\n\n# cube with uvs and normals and six materials and six groups, one for every quad. Translated x:' + pos[ 0 ] );
+	fs.appendFileSync( './verify.obj', vobjCreateVertices( 10, pos ) );
+	fs.appendFileSync( './verify.obj', vobjCreateCubeVVnVt( offsets,
+		[ 'cube6a', 'cube6b', 'cube6c', 'cube6d', 'cube6e', 'cube6f' ],
+		[ 'red', 'blue', 'green', 'lightblue', 'orange', 'purple' ] ) );
+
+	pos[ 0 ] += 50;
+	offsets[ 0 ] += 8;
+	fs.appendFileSync( './verify.obj', '\n\n# Point. Translated x:' + pos[ 0 ] );
+	fs.appendFileSync( './verify.obj', vobjCreateVertices( 10, pos ) );
+	fs.appendFileSync( './verify.obj', '\np -8 -7 -6 -5 -4 -3 -2 -1\n' );
+
+	pos[ 0 ] += 50;
+	offsets[ 0 ] += 8;
+	fs.appendFileSync( './verify.obj', '\n\n# Line. Translated x:' + pos[ 0 ] );
+	fs.appendFileSync( './verify.obj', vobjCreateVertices( 10, pos ) );
+	fs.appendFileSync( './verify.obj', 'l -8 -7 -6 -5 -4 -3 -2 -1 -8 -5 -8 -4 -7 -6 -7 -3 -5 -1 -3 -2 -6 -2 -4 -1\n' );
+
+	pos[ 0 ] += 50;
+	offsets[ 0 ] += 8;
+	fs.appendFileSync( './verify.obj', '\n\n# Line UV. Translated x:' + pos[ 0 ] );
+	fs.appendFileSync( './verify.obj', vobjCreateVertices( 10, pos ) );
+	fs.appendFileSync( './verify.obj', '\nl -8/-2 -7/-1 -6/-2 -5/-1\n' );
+
+
+
+});

+ 237 - 0
examples/models/obj/verify/verify.html

@@ -0,0 +1,237 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - OBJLoader2/OBJLoader verification</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+
+		<style>
+			body {
+				font-family: Monospace;
+				background-color: #000;
+				color: #fff;
+				margin: 0 0 0 0;
+				padding: 0 0 0 0;
+				border: none;
+				cursor: default;
+			}
+			#info {
+				color: #fff;
+				position: absolute;
+				top: 10px;
+				width: 100%;
+				text-align: center;
+				z-index: 100;
+				display:block;
+			}
+			#info a {
+				color: #f00;
+				font-weight: bold;
+				text-decoration: underline;
+				cursor: pointer
+			}
+			#glFullscreen {
+				width: 100%;
+				height: 100vh;
+				min-width: 640px;
+				min-height: 360px;
+				position: relative;
+				overflow: hidden;
+				z-index: 0;
+			}
+			#example {
+				width: 100%;
+				height: 100%;
+				top: 0;
+				left: 0;
+				background-color: #000000;
+			}
+			#feedback {
+				color: darkorange;
+			}
+			#dat {
+				user-select: none;
+				position: absolute;
+				left: 0;
+				top: 0;
+				z-Index: 200;
+			}
+		</style>
+	</head>
+
+	<body>
+		<div id="glFullscreen">
+			<canvas id="example"></canvas>
+		</div>
+		<div id="dat">
+
+		</div>
+		<div id="info">
+			<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - OBJLoader2/OBJLoader verification
+			<div id="feedback"></div>
+		</div>
+
+		<script src="../../../js/Detector.js"></script>
+		<script src="../../../../build/three.js"></script>
+		<script src="../../../js/controls/TrackballControls.js"></script>
+		<script src="../../../js/loaders/MTLLoader.js"></script>
+		<script src="../../../js/loaders/OBJLoader.js"></script>
+		<script src="../../../js/libs/dat.gui.min.js"></script>
+
+		<script src="../../../js/loaders/LoaderSupport.js"></script>
+		<script src="../../../js/loaders/OBJLoader2.js"></script>
+		<script>
+
+			'use strict';
+
+			var OBJLoaderVerify = (function () {
+
+				var Validator = THREE.LoaderSupport.Validator;
+
+				function OBJLoaderVerify( elementToBindTo ) {
+					this.renderer = null;
+					this.canvas = elementToBindTo;
+					this.aspectRatio = 1;
+					this.recalcAspectRatio();
+
+					this.scene = null;
+					this.cameraDefaults = {
+						posCamera: new THREE.Vector3( 0.0, 175.0, 500.0 ),
+						posCameraTarget: new THREE.Vector3( 0, 0, 0 ),
+						near: 0.1,
+						far: 10000,
+						fov: 45
+					};
+					this.camera = null;
+					this.cameraTarget = this.cameraDefaults.posCameraTarget;
+
+					this.controls = null;
+				}
+
+				OBJLoaderVerify.prototype.initGL = function () {
+					this.renderer = new THREE.WebGLRenderer( {
+						canvas: this.canvas,
+						antialias: true,
+						autoClear: true
+					} );
+					this.renderer.setClearColor( 0x050505 );
+
+					this.scene = new THREE.Scene();
+
+					this.camera = new THREE.PerspectiveCamera( this.cameraDefaults.fov, this.aspectRatio, this.cameraDefaults.near, this.cameraDefaults.far );
+					this.resetCamera();
+					this.controls = new THREE.TrackballControls( this.camera, this.renderer.domElement );
+
+					var ambientLight = new THREE.AmbientLight( 0x404040 );
+					var directionalLight1 = new THREE.DirectionalLight( 0xC0C090 );
+					var directionalLight2 = new THREE.DirectionalLight( 0xC0C090 );
+
+					directionalLight1.position.set( -100, -50, 100 );
+					directionalLight2.position.set( 100, 50, -100 );
+
+					this.scene.add( directionalLight1 );
+					this.scene.add( directionalLight2 );
+					this.scene.add( ambientLight );
+
+					var helper = new THREE.GridHelper( 1200, 60, 0xFF4444, 0x404040 );
+					this.scene.add( helper );
+				};
+
+				OBJLoaderVerify.prototype.initContent = function () {
+					var modelName = 'verificationCubes';
+					this._reportProgress( { detail: { text: 'Loading: ' + modelName } } );
+
+					var scope = this;
+					var objLoader2 = new THREE.OBJLoader2();
+
+					var callbackOnLoad = function ( event ) {
+						scope.scene.add( event.detail.loaderRootNode );
+						console.log( 'Loading complete: ' + event.detail.modelName );
+						scope._reportProgress( { detail: { text: '' } } );
+					};
+
+					var onLoadMtl = function ( materials, materialCreator ) {
+						var objLoader = new THREE.OBJLoader();
+						objLoader.setMaterials( materialCreator );
+						objLoader.load( './verify.obj', function ( object ) {
+							object.position.y = -100;
+							scope.scene.add( object );
+						} );
+
+						objLoader2.setModelName( modelName );
+						objLoader2.setMaterials( materials );
+						var mats = objLoader2.builder.getMaterials();
+						var defaultPointMaterial = mats[ 'defaultPointMaterial' ];
+						defaultPointMaterial.sizeAttenuation = true;
+
+						objLoader2.getLogger().setDebug( true );
+						objLoader2.load( './verify.obj', callbackOnLoad, null, null, null, false );
+					};
+					objLoader2.loadMtl( './verify.mtl', null, onLoadMtl, null, { invertTrProperty: false } );
+				};
+
+				OBJLoaderVerify.prototype._reportProgress = function( event ) {
+					var output = Validator.verifyInput( event.detail.text, '' );
+					console.log( 'Progress: ' + output );
+					document.getElementById( 'feedback' ).innerHTML = output;
+				};
+
+				OBJLoaderVerify.prototype.resizeDisplayGL = function () {
+					this.controls.handleResize();
+
+					this.recalcAspectRatio();
+					this.renderer.setSize( this.canvas.offsetWidth, this.canvas.offsetHeight, false );
+
+					this.updateCamera();
+				};
+
+				OBJLoaderVerify.prototype.recalcAspectRatio = function () {
+					this.aspectRatio = ( this.canvas.offsetHeight === 0 ) ? 1 : this.canvas.offsetWidth / this.canvas.offsetHeight;
+				};
+
+				OBJLoaderVerify.prototype.resetCamera = function () {
+					this.camera.position.copy( this.cameraDefaults.posCamera );
+					this.cameraTarget.copy( this.cameraDefaults.posCameraTarget );
+
+					this.updateCamera();
+				};
+
+				OBJLoaderVerify.prototype.updateCamera = function () {
+					this.camera.aspect = this.aspectRatio;
+					this.camera.lookAt( this.cameraTarget );
+					this.camera.updateProjectionMatrix();
+				};
+
+				OBJLoaderVerify.prototype.render = function () {
+					if ( ! this.renderer.autoClear ) this.renderer.clear();
+					this.controls.update();
+					this.renderer.render( this.scene, this.camera );
+				};
+
+				return OBJLoaderVerify;
+
+			})();
+
+			var app = new OBJLoaderVerify( document.getElementById( 'example' ) );
+
+			var resizeWindow = function () {
+				app.resizeDisplayGL();
+			};
+
+			var render = function () {
+				requestAnimationFrame( render );
+				app.render();
+			};
+
+			window.addEventListener( 'resize', resizeWindow, false );
+
+			console.log( 'Starting initialisation phase...' );
+			app.initGL();
+			app.resizeDisplayGL();
+			app.initContent();
+
+			render();
+
+		</script>
+	</body>
+</html>

+ 42 - 0
examples/models/obj/verify/verify.mtl

@@ -0,0 +1,42 @@
+newmtl red
+	Ka 1.000000 0.000000 0.000000
+	Kd 1.000000 0.000000 0.000000
+	Ks 0.000000 0.000000 0.000000
+	illum 2
+	Ns 0.000000
+	map_Kd ../female02/02_-_Default1noCulling.JPG
+
+newmtl blue
+	Ka 0.000000 0.000000 1.000000
+	Kd 0.000000 0.000000 1.000000
+	Ks 0.000000 0.000000 0.000000
+	illum 1
+	Ns 0.000000
+
+newmtl green
+	Ka 0.000000 1.000000 0.000000
+	Kd 0.000000 1.000000 0.000000
+	Ks 0.000000 0.000000 0.000000
+	illum 1
+	Ns 0.000000
+
+newmtl lightblue
+	Ka 0.000000 1.000000 1.000000
+	Kd 0.000000 1.000000 1.000000
+	Ks 0.000000 0.000000 0.000000
+	illum 1
+	Ns 0.000000
+
+newmtl orange
+	Ka 1.000000 0.647059 0.000000
+	Kd 1.000000 0.647059 0.000000
+	Ks 0.000000 0.000000 0.000000
+	illum 1
+	Ns 0.000000
+
+newmtl purple
+	Ka 0.825806 0.000000 0.825806
+	Kd 0.825806 0.000000 0.825806
+	Ks 0.000000 0.000000 0.000000
+	illum 1
+	Ns 0.000000

+ 213 - 0
examples/models/obj/verify/verify.obj

@@ -0,0 +1,213 @@
+# Verification OBJ created with gulp
+
+mtllib verify.mtl
+
+# Cube no materials. Translated x:-150
+v -160 60 10
+v -160 40 10
+v -140 40 10
+v -140 60 10
+v -160 60 -10
+v -160 40 -10
+v -140 40 -10
+v -140 60 -10
+
+f 1 2 3 4
+f 8 7 6 5
+f 4 3 7 8
+f 5 1 4 8
+f 5 6 2 1
+f 2 6 7 3
+
+
+# Cube with two materials. Translated x:-100
+v -110 60 10
+v -110 40 10
+v -90 40 10
+v -90 60 10
+v -110 60 -10
+v -110 40 -10
+v -90 40 -10
+v -90 60 -10
+
+usemtl orange
+f 9 10 11 12
+f 16 15 14 13
+f 12 11 15 16
+usemtl purple
+f 13 9 12 16
+f 13 14 10 9
+f 10 14 15 11
+
+
+# Cube with normals no materials. Translated x:-50
+v -60 60 10
+v -60 40 10
+v -40 40 10
+v -40 60 10
+v -60 60 -10
+v -60 40 -10
+v -40 40 -10
+v -40 60 -10
+
+vn 0 0 1
+vn 0 0 -1
+vn 0 1 0
+vn 0 -1 0
+vn 1 0 0
+vn -1 0 0
+
+g cube3
+usemtl lightblue
+f 17//1 18//1 19//1 20//1
+f 24//2 23//2 22//2 21//2
+f 20//5 19//5 23//5 24//5
+f 21//3 17//3 20//3 24//3
+f 21//6 22//6 18//6 17//6
+f 18//4 22//4 23//4 19//4
+
+
+# Cube with uvs and red material. Translated x:0
+v -10 60 10
+v -10 40 10
+v 10 40 10
+v 10 60 10
+v -10 60 -10
+v -10 40 -10
+v 10 40 -10
+v 10 60 -10
+
+vt 0 1
+vt 1 1
+vt 1 0
+vt 0 0
+
+usemtl red
+f 25/1 26/2 27/3 28/4
+f 32/1 31/2 30/3 29/4
+f 28/1 27/2 31/3 32/4
+f 29/1 25/2 28/3 32/4
+f 29/1 30/2 26/3 25/4
+f 26/1 30/2 31/3 27/4
+
+
+# cube with uvs and normals and material. Translated x50
+v 40 60 10
+v 40 40 10
+v 60 40 10
+v 60 60 10
+v 40 60 -10
+v 40 40 -10
+v 60 40 -10
+v 60 60 -10
+
+usemtl red
+f 33/1/1 34/2/1 35/3/1 36/4/1
+f 40/1/2 39/2/2 38/3/2 37/4/2
+f 36/1/5 35/2/5 39/3/5 40/4/5
+usemtl blue
+f 37/1/3 33/2/3 36/3/3 40/4/3
+f 37/1/6 38/2/6 34/3/6 33/4/6
+usemtl green
+f 34/1/4 38/2/4 39/3/4 35/4/4
+
+
+# cube with uvs and normals and two materials and group for every quad. Translated x:100
+v 90 60 10
+v 90 40 10
+v 110 40 10
+v 110 60 10
+v 90 60 -10
+v 90 40 -10
+v 110 40 -10
+v 110 60 -10
+
+vn 0 0 1
+vn 0 0 -1
+vn 0 1 0
+vn 0 -1 0
+vn 1 0 0
+vn -1 0 0
+
+g cube6a
+usemtl green
+f -8/7/1 -7/8/1 -6/9/1 -5/10/1
+g cube6b
+f -1/7/2 -2/8/2 -3/9/2 -4/10/2
+g cube6c
+f -5/7/5 -6/8/5 -2/9/5 -1/10/5
+g cube6d
+usemtl orange
+f -4/7/3 -8/8/3 -5/9/3 -1/10/3
+g cube6e
+f -4/7/6 -3/8/6 -7/9/6 -8/10/6
+g cube6f
+f -7/7/4 -3/8/4 -2/9/4 -6/10/4
+
+
+# cube with uvs and normals and six materials and six groups, one for every quad. Translated x:150
+v 140 60 10
+v 140 40 10
+v 160 40 10
+v 160 60 10
+v 140 60 -10
+v 140 40 -10
+v 160 40 -10
+v 160 60 -10
+
+g cube6a
+usemtl red
+f 49/7/1 50/8/1 51/9/1 52/10/1
+g cube6b
+usemtl blue
+f 56/7/2 55/8/2 54/9/2 53/10/2
+g cube6c
+usemtl green
+f 52/7/5 51/8/5 55/9/5 56/10/5
+g cube6d
+usemtl lightblue
+f 53/7/3 49/8/3 52/9/3 56/10/3
+g cube6e
+usemtl orange
+f 53/7/6 54/8/6 50/9/6 49/10/6
+g cube6f
+usemtl purple
+f 50/7/4 54/8/4 55/9/4 51/10/4
+
+
+# Point. Translated x:200
+v 190 60 10
+v 190 40 10
+v 210 40 10
+v 210 60 10
+v 190 60 -10
+v 190 40 -10
+v 210 40 -10
+v 210 60 -10
+
+p -8 -7 -6 -5 -4 -3 -2 -1
+
+
+# Line. Translated x:250
+v 240 60 10
+v 240 40 10
+v 260 40 10
+v 260 60 10
+v 240 60 -10
+v 240 40 -10
+v 260 40 -10
+v 260 60 -10
+l -8 -7 -6 -5 -4 -3 -2 -1 -8 -5 -8 -4 -7 -6 -7 -3 -5 -1 -3 -2 -6 -2 -4 -1
+
+
+# Line UV. Translated x:300
+v 290 60 10
+v 290 40 10
+v 310 40 10
+v 310 60 10
+v 290 60 -10
+v 290 40 -10
+v 310 40 -10
+v 310 60 -10
+
+l -8/-2 -7/-1 -6/-2 -5/-1

+ 0 - 47
examples/obj/cubes/cubes.mtl

@@ -1,47 +0,0 @@
-newmtl red
-Ka 1.000000 0.000000 0.000000
-Kd 1.000000 0.000000 0.000000
-Ks 0.000000 0.000000 0.000000
-Tr 1.000000
-illum 1
-Ns 0.000000
-
-newmtl blue
-Ka 0.000000 0.000000 1.000000
-Kd 0.000000 0.000000 1.000000
-Ks 0.000000 0.000000 0.000000
-Tr 1.000000
-illum 1
-Ns 0.000000
-
-newmtl green
-Ka 0.000000 1.000000 0.000000
-Kd 0.000000 1.000000 0.000000
-Ks 0.000000 0.000000 0.000000
-Tr 1.000000
-illum 1
-Ns 0.000000
-
-newmtl lightblue
-Ka 0.000000 1.000000 1.000000
-Kd 0.000000 1.000000 1.000000
-Ks 0.000000 0.000000 0.000000
-Tr 1.000000
-illum 1
-Ns 0.000000
-
-newmtl orange
-Ka 1.000000 0.647059 0.000000
-Kd 1.000000 0.647059 0.000000
-Ks 0.000000 0.000000 0.000000
-Tr 1.000000
-illum 1
-Ns 0.000000
-
-newmtl purple
-Ka 0.825806 0.000000 0.825806
-Kd 0.825806 0.000000 0.825806
-Ks 0.000000 0.000000 0.000000
-Tr 1.000000
-illum 1
-Ns 0.000000

+ 0 - 57
examples/obj/cubes/cubes.obj

@@ -1,57 +0,0 @@
-mtllib cubes.mtl
-
-# cube 01: pair of group and material per side/quad
-o cube 01
-
-v -10.00000 10.00000 10.00000
-v -10.00000 -10.00000 10.00000
-v 10.00000 -10.00000 10.00000
-v 10.00000 10.00000 10.00000
-v -10.00000 10.00000 -10.00000
-v -10.00000 -10.00000 -10.00000
-v 10.00000 -10.00000 -10.00000
-v 10.00000 10.00000 -10.00000
-
-g front
-usemtl red
-f 1 2 3 4
-g back
-usemtl blue
-f 8 7 6 5
-g right
-usemtl green
-f 4 3 7 8
-g top
-usemtl lightblue
-f 5 1 4 8
-g left
-usemtl orange
-f 5 6 2 1
-g bottom
-usemtl purple
-f 2 6 7 3
-
-# cube 02: one pair of group and material with different smoothing groups
-o cube 02
-
-v 20.00000 10.00000 10.00000
-v 20.00000 -10.00000 10.00000
-v 40.00000 -10.00000 10.00000
-v 40.00000 10.00000 10.00000
-v 20.00000 10.00000 -10.00000
-v 20.00000 -10.00000 -10.00000
-v 40.00000 -10.00000 -10.00000
-v 40.00000 10.00000 -10.00000
-
-g cube 02 one group
-usemtl blue
-s 0
-f 9 10 11 12
-f 16 15 14 13
-s 1
-f 12 11 15 16
-f 13 9 12 16
-s 2
-f 13 14 10 9
-s off
-f 10 14 15 11

+ 18 - 22
examples/webgl_loader_obj2_meshspray.html

@@ -85,28 +85,25 @@
 
 			var MeshSpray = (function () {
 
-				var Validator = THREE.LoaderSupport.Validator;
-				var ConsoleLogger = THREE.LoaderSupport.ConsoleLogger;
-
 				MeshSpray.prototype = Object.create( THREE.LoaderSupport.LoaderBase.prototype );
 				MeshSpray.prototype.constructor = MeshSpray;
 
 				function MeshSpray( manager, logger ) {
 					THREE.LoaderSupport.LoaderBase.call( this, manager, logger );
 					this.workerSupport = null;
-					this.logger = new ConsoleLogger();
+					this.logger = new THREE.LoaderSupport.ConsoleLogger();
 				};
 
 				MeshSpray.prototype.run = function ( prepData, workerSupportExternal ) {
 
-					if ( Validator.isValid( workerSupportExternal ) ) {
+					if ( THREE.LoaderSupport.Validator.isValid( workerSupportExternal ) ) {
 
 						this.workerSupport = workerSupportExternal;
 						this.logger = workerSupportExternal.logger;
 
 					} else {
 
-						this.workerSupport = Validator.verifyInput( this.workerSupport, new THREE.LoaderSupport.WorkerSupport() );
+						this.workerSupport = THREE.LoaderSupport.Validator.verifyInput( this.workerSupport, new THREE.LoaderSupport.WorkerSupport() );
 
 					}
 
@@ -125,7 +122,7 @@
 					};
 					var scopeFuncComplete = function ( message ) {
 						var callback = scope.callbacks.onLoad;
-						if ( Validator.isValid( callback ) ) callback(
+						if ( THREE.LoaderSupport.Validator.isValid( callback ) ) callback(
 							{
 								detail: {
 									loaderRootNode: scope.loaderRootNode,
@@ -137,19 +134,20 @@
 						scope.logger.logTimeEnd( 'MeshSpray' );
 					};
 
-					var buildCode = function ( funcBuildObject, funcBuildSingelton ) {
+					var buildCode = function ( funcBuildObject, funcBuildSingleton ) {
 						var workerCode = '';
 						workerCode += '/**\n';
 						workerCode += '  * This code was constructed by MeshSpray buildCode.\n';
 						workerCode += '  */\n\n';
-						workerCode += funcBuildObject( 'Validator', Validator );
-						workerCode += funcBuildSingelton( 'ConsoleLogger', 'ConsoleLogger', ConsoleLogger );
-						workerCode += funcBuildSingelton( 'Parser', 'Parser', Parser );
+						workerCode += 'THREE.LoaderSupport = {};\n\n';
+						workerCode += funcBuildObject( 'THREE.LoaderSupport.Validator', THREE.LoaderSupport.Validator );
+						workerCode += funcBuildSingleton( 'THREE.LoaderSupport.ConsoleLogger', THREE.LoaderSupport.ConsoleLogger );
+						workerCode += funcBuildSingleton( 'Parser', Parser );
 
 						return workerCode;
 					};
 					var libs2Load = [ 'build/three.min.js' ];
-					this.workerSupport.validate( buildCode, libs2Load, '../' );
+					this.workerSupport.validate( buildCode, 'Parser', libs2Load, '../' );
 					this.workerSupport.setCallbacks( scopeBuilderFunc, scopeFuncComplete );
 					this.workerSupport.run(
 						{
@@ -175,8 +173,6 @@
 
 				var Parser  = ( function () {
 
-					var ConsoleLogger = THREE.LoaderSupport.ConsoleLogger;
-
 					function Parser() {
 						this.sizeFactor = 0.5;
 						this.localOffsetFactor = 1.0;
@@ -186,7 +182,7 @@
 						this.quantity = 1;
 						this.callbackBuilder = null;
 						this.callbackProgress = null;
-						this.logger = new ConsoleLogger();
+						this.logger = new THREE.LoaderSupport.ConsoleLogger();
 						this.serializedMaterials = null;
 					};
 
@@ -265,16 +261,16 @@
 						 *
 						 * This is not the most effective way, but outlining possibilities
 						 */
-						var materialName = 'vertexColorMaterial_double';
-						var vertexColorMaterialJson = this.serializedMaterials[ 'vertexColorMaterial' ];
+						var materialName = 'defaultVertexColorMaterial_double';
+						var defaultVertexColorMaterialJson = this.serializedMaterials[ 'defaultVertexColorMaterial' ];
 						var loader = new THREE.MaterialLoader();
 
-						var vertexColorMaterialDouble = loader.parse( vertexColorMaterialJson );
-						vertexColorMaterialDouble.name = materialName;
-						vertexColorMaterialDouble.side = THREE.DoubleSide;
+						var defaultVertexColorMaterialDouble = loader.parse( defaultVertexColorMaterialJson );
+						defaultVertexColorMaterialDouble.name = materialName;
+						defaultVertexColorMaterialDouble.side = THREE.DoubleSide;
 
 						var newSerializedMaterials = {};
-						newSerializedMaterials[ materialName ] = vertexColorMaterialDouble.toJSON();
+						newSerializedMaterials[ materialName ] = defaultVertexColorMaterialDouble.toJSON();
 						var payload = {
 							cmd: 'materialData',
 							materials: {
@@ -319,7 +315,7 @@
 
 
 				Parser.prototype.setSerializedMaterials = function ( serializedMaterials ) {
-					if ( Validator.isValid( serializedMaterials ) ) {
+					if ( THREE.LoaderSupport.Validator.isValid( serializedMaterials ) ) {
 
 						this.serializedMaterials = serializedMaterials;
 

+ 2 - 2
examples/webgl_loader_obj2_options.html

@@ -261,9 +261,9 @@
 						objLoader.setModelName( modelName );
 						objLoader.setMaterials( materials );
 						objLoader.terminateWorkerOnLoad = false;
-						objLoader.load( 'obj/walt/WaltHead.obj', callbackOnLoad, null, null, null, true );
+						objLoader.load( 'models/obj/walt/WaltHead.obj', callbackOnLoad, null, null, null, true );
 					};
-					objLoader.loadMtl( 'obj/walt/WaltHead.mtl', null, onLoadMtl );
+					objLoader.loadMtl( 'models/obj/walt/WaltHead.mtl', null, onLoadMtl );
 				};
 
 				WWOBJLoader2Example.prototype.useRunSync = function () {

+ 2 - 2
examples/webgl_loader_obj2_run_director.html

@@ -303,8 +303,8 @@
 					modelPrepDatas.push( prepData );
 
 					prepData = new THREE.LoaderSupport.PrepData( 'WaltHead' );
-					prepData.addResource( new THREE.LoaderSupport.ResourceDescriptor( 'obj/walt/WaltHead.obj', 'OBJ' ) );
-					prepData.addResource( new THREE.LoaderSupport.ResourceDescriptor( 'obj/walt/WaltHead.mtl', 'MTL' ) );
+					prepData.addResource( new THREE.LoaderSupport.ResourceDescriptor( 'models/obj/walt/WaltHead.obj', 'OBJ' ) );
+					prepData.addResource( new THREE.LoaderSupport.ResourceDescriptor( 'models/obj/walt/WaltHead.mtl', 'MTL' ) );
 					modelPrepDatas.push( prepData );
 
 					var pivot;

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio