Browse Source

Merge branch 'dev' into FBXLoader_check_translate_scale_params_defined_per_frame

Lewy Blue 7 năm trước cách đây
mục cha
commit
3cfb352064

+ 0 - 6
docs/api/objects/SkinnedMesh.html

@@ -97,12 +97,6 @@
 		The base matrix that is used for resetting the bound bone transforms.
 		</div>
 
-		<h3>[property:array bones]</h3>
-		<div>
-		This contains the array of [page:Bone bones] for this mesh. These should be set in
-		the constructor.
-		</div>
-
 		<h3>[property:Boolean isSkinnedMesh]</h3>
 		<div>
 			Used to check whether this or derived classes are skinned meshes. Default is *true*.<br /><br />

+ 85 - 122
examples/js/loaders/FBXLoader.js

@@ -328,8 +328,7 @@
 
 			fileName = imageMap.get( children[ 0 ].ID );
 
-		} else if ( relativeFilePath !== undefined && relativeFilePath[ 0 ] !== '/' &&
-			relativeFilePath.match( /^[a-zA-Z]:/ ) === null ) {
+		} else if ( relativeFilePath !== undefined && relativeFilePath[ 0 ] !== '/' && relativeFilePath.match( /^[a-zA-Z]:/ ) === null ) {
 
 			// use textureNode.properties.RelativeFilename
 			// if it exists and it doesn't seem an absolute path
@@ -657,15 +656,15 @@
 				index: i,
 				indices: [],
 				weights: [],
-				transform: parseMatrixArray( subDeformerNode.subNodes.Transform.properties.a ),
-				transformLink: parseMatrixArray( subDeformerNode.subNodes.TransformLink.properties.a ),
+				transform: new THREE.Matrix4().fromArray( subDeformerNode.subNodes.Transform.properties.a ),
+				transformLink: new THREE.Matrix4().fromArray( subDeformerNode.subNodes.TransformLink.properties.a ),
 				linkMode: subDeformerNode.properties.Mode
 			};
 
 			if ( 'Indexes' in subDeformerNode.subNodes ) {
 
-				subDeformer.indices = parseIntArray( subDeformerNode.subNodes.Indexes.properties.a );
-				subDeformer.weights = parseFloatArray( subDeformerNode.subNodes.Weights.properties.a );
+				subDeformer.indices = subDeformerNode.subNodes.Indexes.properties.a;
+				subDeformer.weights = subDeformerNode.subNodes.Weights.properties.a;
 
 			}
 
@@ -764,8 +763,8 @@
 
 		// First, each index is going to be its own vertex.
 
-		var vertexBuffer = parseFloatArray( subNodes.Vertices.properties.a );
-		var indexBuffer = parseIntArray( subNodes.PolygonVertexIndex.properties.a );
+		var vertexBuffer = subNodes.Vertices.properties.a;
+		var indexBuffer = subNodes.PolygonVertexIndex.properties.a;
 
 		if ( subNodes.LayerElementNormal ) {
 
@@ -1017,43 +1016,47 @@
 
 		}
 
-		// Convert the material indices of each vertex into rendering groups on the geometry.
+		if ( materialInfo && materialInfo.mappingType !== 'AllSame' ) {
 
-		var materialIndexBuffer = bufferInfo.materialIndexBuffer;
-		var prevMaterialIndex = materialIndexBuffer[ 0 ];
-		var startIndex = 0;
+			// Convert the material indices of each vertex into rendering groups on the geometry.
+			var materialIndexBuffer = bufferInfo.materialIndexBuffer;
+			var prevMaterialIndex = materialIndexBuffer[ 0 ];
+			var startIndex = 0;
 
-		for ( var i = 0; i < materialIndexBuffer.length; ++ i ) {
+			for ( var i = 0; i < materialIndexBuffer.length; ++ i ) {
 
-			if ( materialIndexBuffer[ i ] !== prevMaterialIndex ) {
+				if ( materialIndexBuffer[ i ] !== prevMaterialIndex ) {
 
-				geo.addGroup( startIndex, i - startIndex, prevMaterialIndex );
+					geo.addGroup( startIndex, i - startIndex, prevMaterialIndex );
 
-				prevMaterialIndex = materialIndexBuffer[ i ];
-				startIndex = i;
+					prevMaterialIndex = materialIndexBuffer[ i ];
+					startIndex = i;
+
+				}
 
 			}
 
-		}
+			// the loop above doesn't add the last group, do that here.
+			if ( geo.groups.length > 0 ) {
 
-		// the loop above doesn't add the last group, do that here.
-		if ( geo.groups.length > 0 ) {
+				var lastGroup = geo.groups[ geo.groups.length - 1 ];
+				var lastIndex = lastGroup.start + lastGroup.count;
 
-			var lastGroup = geo.groups[ geo.groups.length - 1 ];
-			var lastIndex = lastGroup.start + lastGroup.count;
+				if ( lastIndex !== materialIndexBuffer.length ) {
 
-			if ( lastIndex !== materialIndexBuffer.length ) {
+					geo.addGroup( lastIndex, materialIndexBuffer.length - lastIndex, prevMaterialIndex );
 
-				geo.addGroup( lastIndex, materialIndexBuffer.length - lastIndex, prevMaterialIndex );
+				}
 
 			}
 
-		}
+			// case where there are multiple materials but the whole geometry is only
+			// using one of them
+			if ( geo.groups.length === 0 ) {
 
-		// catch case where the whole geometry has a single non-zero index
-		if ( geo.groups.length === 0 && materialIndexBuffer[ 0 ] !== 0 ) {
+				geo.addGroup( 0, materialIndexBuffer.length, materialIndexBuffer[ 0 ] );
 
-			geo.addGroup( 0, materialIndexBuffer.length, materialIndexBuffer[ 0 ] );
+			}
 
 		}
 
@@ -1070,17 +1073,17 @@
 
 		var mappingType = NormalNode.properties.MappingInformationType;
 		var referenceType = NormalNode.properties.ReferenceInformationType;
-		var buffer = parseFloatArray( NormalNode.subNodes.Normals.properties.a );
+		var buffer = NormalNode.subNodes.Normals.properties.a;
 		var indexBuffer = [];
 		if ( referenceType === 'IndexToDirect' ) {
 
 			if ( 'NormalIndex' in NormalNode.subNodes ) {
 
-				indexBuffer = parseIntArray( NormalNode.subNodes.NormalIndex.properties.a );
+				indexBuffer = NormalNode.subNodes.NormalIndex.properties.a;
 
 			} else if ( 'NormalsIndex' in NormalNode.subNodes ) {
 
-				indexBuffer = parseIntArray( NormalNode.subNodes.NormalsIndex.properties.a );
+				indexBuffer = NormalNode.subNodes.NormalsIndex.properties.a;
 
 			}
 
@@ -1105,11 +1108,11 @@
 
 		var mappingType = UVNode.properties.MappingInformationType;
 		var referenceType = UVNode.properties.ReferenceInformationType;
-		var buffer = parseFloatArray( UVNode.subNodes.UV.properties.a );
+		var buffer = UVNode.subNodes.UV.properties.a;
 		var indexBuffer = [];
 		if ( referenceType === 'IndexToDirect' ) {
 
-			indexBuffer = parseIntArray( UVNode.subNodes.UVIndex.properties.a );
+			indexBuffer = UVNode.subNodes.UVIndex.properties.a;
 
 		}
 
@@ -1132,11 +1135,11 @@
 
 		var mappingType = ColorNode.properties.MappingInformationType;
 		var referenceType = ColorNode.properties.ReferenceInformationType;
-		var buffer = parseFloatArray( ColorNode.subNodes.Colors.properties.a );
+		var buffer = ColorNode.subNodes.Colors.properties.a;
 		var indexBuffer = [];
 		if ( referenceType === 'IndexToDirect' ) {
 
-			indexBuffer = parseFloatArray( ColorNode.subNodes.ColorIndex.properties.a );
+			indexBuffer = ColorNode.subNodes.ColorIndex.properties.a;
 
 		}
 
@@ -1172,7 +1175,7 @@
 
 		}
 
-		var materialIndexBuffer = parseIntArray( MaterialNode.subNodes.Materials.properties.a );
+		var materialIndexBuffer = MaterialNode.subNodes.Materials.properties.a;
 
 		// Since materials are stored as indices, there's a bit of a mismatch between FBX and what
 		// we expect.  So we create an intermediate buffer that points to the index in the buffer,
@@ -1360,9 +1363,9 @@
 
 		var degree = order - 1;
 
-		var knots = parseFloatArray( geometryNode.subNodes.KnotVector.properties.a );
+		var knots = geometryNode.subNodes.KnotVector.properties.a;
 		var controlPoints = [];
-		var pointsValues = parseFloatArray( geometryNode.subNodes.Points.properties.a );
+		var pointsValues = geometryNode.subNodes.Points.properties.a;
 
 		for ( var i = 0, l = pointsValues.length; i < l; i += 4 ) {
 
@@ -1808,7 +1811,7 @@
 
 			if ( 'Lcl_Rotation' in node.properties ) {
 
-				var rotation = node.properties.Lcl_Rotation.value.map( degreeToRadian );
+				var rotation = node.properties.Lcl_Rotation.value.map( THREE.Math.degToRad );
 				rotation.push( 'ZYX' );
 				model.rotation.fromArray( rotation );
 
@@ -1822,7 +1825,7 @@
 
 			if ( 'PreRotation' in node.properties ) {
 
-				var preRotations = new THREE.Euler().setFromVector3( parseVector3( node.properties.PreRotation ).multiplyScalar( DEG2RAD ), 'ZYX' );
+				var preRotations = new THREE.Euler().fromArray( node.properties.PreRotation.value.map( THREE.Math.degToRad ), 'ZYX' );
 				preRotations = new THREE.Quaternion().setFromEuler( preRotations );
 				var currentRotation = new THREE.Quaternion().setFromEuler( model.rotation );
 				preRotations.multiply( currentRotation );
@@ -1935,7 +1938,7 @@
 
 				var node = PoseNode[ PoseNodeIndex ];
 
-				var rawMatWrd = parseMatrixArray( node.subNodes.Matrix.properties.a );
+				var rawMatWrd = new THREE.Matrix4().fromArray( node.subNodes.Matrix.properties.a );
 
 				worldMatrices.set( parseInt( node.id ), rawMatWrd );
 
@@ -2616,6 +2619,7 @@
 
 			}
 			returnObject.curves.get( id )[ curveNode.attr ] = curveNode;
+
 			if ( curveNode.attr === 'R' ) {
 
 				var curves = curveNode.curves;
@@ -2654,9 +2658,9 @@
 
 				}
 
-				curves.x.values = curves.x.values.map( degreeToRadian );
-				curves.y.values = curves.y.values.map( degreeToRadian );
-				curves.z.values = curves.z.values.map( degreeToRadian );
+				curves.x.values = curves.x.values.map( THREE.Math.degToRad );
+				curves.y.values = curves.y.values.map( THREE.Math.degToRad );
+				curves.z.values = curves.z.values.map( THREE.Math.degToRad );
 
 				if ( curveNode.preRotations !== null ) {
 
@@ -3012,11 +3016,11 @@
 			version: null,
 			id: animationCurve.id,
 			internalID: animationCurve.id,
-			times: parseFloatArray( animationCurve.subNodes.KeyTime.properties.a ).map( convertFBXTimeToSeconds ),
-			values: parseFloatArray( animationCurve.subNodes.KeyValueFloat.properties.a ),
+			times: animationCurve.subNodes.KeyTime.properties.a.map( convertFBXTimeToSeconds ),
+			values: animationCurve.subNodes.KeyValueFloat.properties.a,
 
-			attrFlag: parseIntArray( animationCurve.subNodes.KeyAttrFlags.properties.a ),
-			attrData: parseFloatArray( animationCurve.subNodes.KeyAttrDataFloat.properties.a )
+			attrFlag: animationCurve.subNodes.KeyAttrFlags.properties.a,
+			attrData: animationCurve.subNodes.KeyAttrDataFloat.properties.a,
 		};
 
 	}
@@ -4069,7 +4073,7 @@
 
 	} );
 
-	function TextParser() { }
+	function TextParser() {}
 
 	Object.assign( TextParser.prototype, {
 
@@ -4194,15 +4198,8 @@
 
 				}
 
-				// for special case,
-				//
-				//	  Vertices: *8670 {
-				//		  a: 0.0356229953467846,13.9599733352661,-0.399196773.....(snip)
-				// -0.0612030513584614,13.960485458374,-0.409748703241348,-0.10.....
-				// 0.12490539252758,13.7450733184814,-0.454119384288788,0.09272.....
-				// 0.0836158767342567,13.5432004928589,-0.435397416353226,0.028.....
-				//
-				// in these case the lines must continue from the previous line
+				// large arrays are split over multiple lines terminated with a ',' character
+				// if this is encountered the line needs to be joined to the previous line
 				if ( l.match( /^[^\s\t}]/ ) ) {
 
 					this.parseNodePropertyContinued( l );
@@ -4377,7 +4374,6 @@
 			// already exists in properties, then append this
 			if ( propName in currentNode.properties ) {
 
-				// console.log( "duped entry found\nkey: " + propName + "\nvalue: " + propValue );
 				if ( Array.isArray( currentNode.properties[ propName ] ) ) {
 
 					currentNode.properties[ propName ].push( propValue );
@@ -4404,13 +4400,28 @@
 
 			this.setCurrentProp( currentNode.properties, propName );
 
+			// convert string to array, unless it ends in ',' in which case more will be added to it
+			if ( propName === 'a' && propValue.slice( - 1 ) !== ',' ) {
+
+				currentNode.properties.a = parseNumberArray( propValue );
+
+			}
+
 		},
 
-		// TODO:
 		parseNodePropertyContinued: function ( line ) {
 
 			this.currentProp[ this.currentPropName ] += line;
 
+			// if the line doesn't end in ',' we have reached the end of the property value
+			// so convert the string to an array
+			if ( line.slice( - 1 ) !== ',' ) {
+
+				var currentNode = this.getCurrentNode();
+				currentNode.properties.a = parseNumberArray( currentNode.properties.a );
+
+			}
+
 		},
 
 		parseNodeSpecialProperty: function ( line, propName, propValue ) {
@@ -4460,7 +4471,7 @@
 				case 'Lcl_Translation':
 				case 'Lcl_Rotation':
 				case 'Lcl_Scaling':
-					innerPropValue = parseFloatArray( innerPropValue );
+					innerPropValue = parseNumberArray( innerPropValue );
 					break;
 
 			}
@@ -4498,7 +4509,7 @@
 	// Binary format specification:
 	//   https://code.blender.org/2013/08/fbx-binary-file-format-specification/
 	//   https://wiki.rogiken.org/specifications/file-format/fbx/ (more detail but Japanese)
-	function BinaryParser() { }
+	function BinaryParser() {}
 
 	Object.assign( BinaryParser.prototype, {
 
@@ -4614,18 +4625,10 @@
 
 					if ( Array.isArray( value ) ) {
 
-						// node represents
-						//	Vertices: *3 {
-						//		a: 0.01, 0.02, 0.03
-						//	}
-						// of text format here.
-
 						node.properties[ node.name ] = node.propertyList[ 0 ];
 						subNodes[ node.name ] = node;
 
-						// Later phase expects single property array is in node.properties.a as String.
-						// TODO: optimize
-						node.properties.a = value.toString();
+						node.properties.a = value;
 
 					} else {
 
@@ -4696,8 +4699,7 @@
 					if ( innerPropName.indexOf( 'Lcl ' ) === 0 ) innerPropName = innerPropName.replace( 'Lcl ', 'Lcl_' );
 					if ( innerPropType1.indexOf( 'Lcl ' ) === 0 ) innerPropType1 = innerPropType1.replace( 'Lcl ', 'Lcl_' );
 
-					if ( innerPropType1 === 'ColorRGB' || innerPropType1 === 'Vector' ||
-						innerPropType1 === 'Vector3D' || innerPropType1.indexOf( 'Lcl_' ) === 0 ) {
+					if ( innerPropType1 === 'ColorRGB' || innerPropType1 === 'Vector' || innerPropType1 === 'Vector3D' || innerPropType1.indexOf( 'Lcl_' ) === 0 ) {
 
 						innerPropValue = [
 							node.propertyList[ 4 ],
@@ -5256,7 +5258,7 @@
 	} );
 
 
-	function FBXTree() { }
+	function FBXTree() {}
 
 	Object.assign( FBXTree.prototype, {
 
@@ -5353,8 +5355,8 @@
 
 			} else {
 
-				this.__cache_search_connection_children[ id ] = [];
-				return [];
+				this.__cache_search_connection_children[ id ] = [ ];
+				return [ ];
 
 			}
 
@@ -5476,15 +5478,18 @@
 	}
 
 	/**
-	 * Parses comma separated list of float numbers and returns them in an array.
+	 * Parses comma separated list of numbers and returns them in an array.
+	 * If an array is passed just return it - this is because the TextParser sometimes
+	 * returns strings instead of arrays, while the BinaryParser always returns arrays
+	 * TODO: this function should only need to be called from inside the TextParser
 	 * @example
 	 * // Returns [ 5.6, 9.4, 2.5, 1.4 ]
-	 * parseFloatArray( "5.6,9.4,2.5,1.4" )
+	 * parseNumberArray( "5.6,9.4,2.5,1.4" )
 	 * @returns {number[]}
 	 */
-	function parseFloatArray( string ) {
+	function parseNumberArray( value ) {
 
-		var array = string.split( ',' );
+		var array = value.split( ',' );
 
 		for ( var i = 0, l = array.length; i < l; i ++ ) {
 
@@ -5496,27 +5501,6 @@
 
 	}
 
-	/**
-	 * Parses comma separated list of int numbers and returns them in an array.
-	 * @example
-	 * // Returns [ 5, 8, 2, 3 ]
-	 * parseFloatArray( "5,8,2,3" )
-	 * @returns {number[]}
-	 */
-	function parseIntArray( string ) {
-
-		var array = string.split( ',' );
-
-		for ( var i = 0, l = array.length; i < l; i ++ ) {
-
-			array[ i ] = parseInt( array[ i ] );
-
-		}
-
-		return array;
-
-	}
-
 	/**
 	 * Parses Vector3 property from FBXTree.  Property is given as .value.x, .value.y, etc.
 	 * @param {FBXVector3} property - Property to parse as Vector3.
@@ -5539,12 +5523,6 @@
 
 	}
 
-	function parseMatrixArray( floatString ) {
-
-		return new THREE.Matrix4().fromArray( parseFloatArray( floatString ) );
-
-	}
-
 	/**
 	 * Converts ArrayBuffer to String.
 	 * @param {ArrayBuffer} buffer
@@ -5577,21 +5555,6 @@
 
 	}
 
-	/**
-	 * Converts number from degrees into radians.
-	 * @param {number} value
-	 * @returns {number}
-	 */
-	function degreeToRadian( value ) {
-
-		return value * DEG2RAD;
-
-	}
-
-	var DEG2RAD = Math.PI / 180;
-
-	//
-
 	function findIndex( array, func ) {
 
 		for ( var i = 0, l = array.length; i < l; i ++ ) {

+ 14 - 6
examples/js/loaders/GLTFLoader.js

@@ -68,16 +68,24 @@ THREE.GLTFLoader = ( function () {
 			var content;
 			var extensions = {};
 
-			var magic = convertUint8ArrayToString( new Uint8Array( data, 0, 4 ) );
+			if ( typeof data === 'string' ) {
 
-			if ( magic === BINARY_EXTENSION_HEADER_MAGIC ) {
-
-				extensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data );
-				content = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content;
+				content = data;
 
 			} else {
 
-				content = convertUint8ArrayToString( new Uint8Array( data ) );
+				var magic = convertUint8ArrayToString( new Uint8Array( data, 0, 4 ) );
+
+				if ( magic === BINARY_EXTENSION_HEADER_MAGIC ) {
+
+					extensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data );
+					content = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content;
+
+				} else {
+
+					content = convertUint8ArrayToString( new Uint8Array( data ) );
+
+				}
 
 			}
 

+ 28 - 14
examples/js/loaders/LoaderSupport.js

@@ -891,7 +891,7 @@ THREE.LoaderSupport.WorkerRunnerRefImpl = (function () {
 	function WorkerRunnerRefImpl() {
 		var scope = this;
 		var scopedRunner = function( event ) {
-			scope.run( event.data );
+			scope.processMessage( event.data );
 		};
 		self.addEventListener( 'message', scopedRunner, false );
 	}
@@ -927,12 +927,15 @@ THREE.LoaderSupport.WorkerRunnerRefImpl = (function () {
 	 *
 	 * @param {Object} payload Raw mesh description (buffers, params, materials) used to build one to many meshes.
 	 */
-	WorkerRunnerRefImpl.prototype.run = function ( payload ) {
-		var logger = new ConsoleLogger( payload.logger.enabled, payload.logger.debug );
+	WorkerRunnerRefImpl.prototype.processMessage = function ( payload ) {
+		var logger = new ConsoleLogger();
+		if ( Validator.isValid( payload.logger ) ) {
 
-		if ( payload.cmd === 'run' ) {
+			logger.setEnabled( payload.logger.enabled );
+			logger.setDebug( payload.logger.debug );
 
-			logger.logInfo( 'WorkerRunner: Starting Run...' );
+		}
+		if ( payload.cmd === 'run' ) {
 
 			var callbacks = {
 				callbackBuilder: function ( payload ) {
@@ -948,7 +951,8 @@ THREE.LoaderSupport.WorkerRunnerRefImpl = (function () {
 			this.applyProperties( parser, payload.params );
 			this.applyProperties( parser, payload.materials );
 			this.applyProperties( parser, callbacks );
-			parser.parse( payload.buffers.input );
+			parser.workerScope = self;
+			parser.parse( payload.data.input, payload.data.options );
 
 			logger.logInfo( 'WorkerRunner: Run complete!' );
 
@@ -976,7 +980,7 @@ THREE.LoaderSupport.WorkerRunnerRefImpl = (function () {
  */
 THREE.LoaderSupport.WorkerSupport = (function () {
 
-	var WORKER_SUPPORT_VERSION = '1.1.0';
+	var WORKER_SUPPORT_VERSION = '1.1.1';
 
 	var Validator = THREE.LoaderSupport.Validator;
 
@@ -1046,11 +1050,17 @@ THREE.LoaderSupport.WorkerSupport = (function () {
 			var scope = this;
 			var buildWorkerCode = function ( baseWorkerCode ) {
 				scope.workerCode = baseWorkerCode;
+				if ( workerRunner == THREE.LoaderSupport.WorkerRunnerRefImpl ) {
+
+					scope.workerCode += buildObject( 'Validator', THREE.LoaderSupport.Validator );
+					scope.workerCode += buildSingelton( 'ConsoleLogger', 'ConsoleLogger', THREE.LoaderSupport.ConsoleLogger );
+
+				}
 				scope.workerCode += functionCodeBuilder( buildObject, buildSingelton );
 				scope.workerCode += buildSingelton( workerRunner.name, workerRunner.name, workerRunner );
 				scope.workerCode += 'new ' + workerRunner.name + '();\n\n';
 
-				var blob = new Blob( [ scope.workerCode ], { type: 'text/plain' } );
+				var blob = new Blob( [ scope.workerCode ], { type: 'application/javascript' } );
 				scope.worker = new Worker( window.URL.createObjectURL( blob ) );
 				scope.logger.logTimeEnd( 'buildWebWorkerCode' );
 
@@ -1059,10 +1069,8 @@ THREE.LoaderSupport.WorkerSupport = (function () {
 
 					switch ( payload.cmd ) {
 						case 'meshData':
-							scope.callbacks.builder( payload );
-							break;
-
 						case 'materialData':
+						case 'imageData':
 							scope.callbacks.builder( payload );
 							break;
 
@@ -1072,14 +1080,18 @@ THREE.LoaderSupport.WorkerSupport = (function () {
 
 							if ( scope.terminateRequested ) {
 
-								scope.logger.logInfo( 'WorkerSupport: Run is complete. Terminating application on request!' );
+								scope.logger.logInfo( 'WorkerSupport [' + workerRunner + ']: Run is complete. Terminating application on request!' );
 								scope.terminateWorker();
 
 							}
 							break;
 
+						case 'error':
+							scope.logger.logError( 'WorkerSupport [' + workerRunner + ']: Reported error: ' + payload.msg );
+							break;
+
 						default:
-							scope.logger.logError( 'WorkerSupport: Received unknown command: ' + payload.cmd );
+							scope.logger.logError( 'WorkerSupport [' + workerRunner + ']: Received unknown command: ' + payload.cmd );
 							break;
 
 					}
@@ -1183,6 +1195,7 @@ THREE.LoaderSupport.WorkerSupport = (function () {
 	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 funcString;
 		var objectPart;
@@ -1223,8 +1236,9 @@ THREE.LoaderSupport.WorkerSupport = (function () {
 		if ( ! Validator.isValid( this.callbacks.builder ) ) throw 'Unable to run as no "builder" callback is set.';
 		if ( ! Validator.isValid( this.callbacks.onLoad ) ) throw 'Unable to run as no "onLoad" callback is set.';
 		if ( Validator.isValid( this.worker ) || this.loading ) {
-			this.running = true;
+			if ( payload.cmd !== 'run' ) payload.cmd = 'run';
 			this.queuedMessage = payload;
+			this.running = true;
 			this._postMessage();
 
 		}

+ 15 - 18
examples/js/loaders/OBJLoader2.js

@@ -16,7 +16,7 @@ if ( THREE.OBJLoader2 === undefined ) { THREE.OBJLoader2 = {} }
  */
 THREE.OBJLoader2 = (function () {
 
-	var OBJLOADER2_VERSION = '2.1.0';
+	var OBJLOADER2_VERSION = '2.1.1';
 	var LoaderBase = THREE.LoaderSupport.LoaderBase;
 	var Validator = THREE.LoaderSupport.Validator;
 	var ConsoleLogger = THREE.LoaderSupport.ConsoleLogger;
@@ -254,12 +254,10 @@ THREE.OBJLoader2 = (function () {
 		var buildCode = function ( funcBuildObject, funcBuildSingelton ) {
 			var workerCode = '';
 			workerCode += '/**\n';
-			workerCode += '  * This code was constructed by OBJLoader2 buildWorkerCode.\n';
+			workerCode += '  * This code was constructed by OBJLoader2 buildCode.\n';
 			workerCode += '  */\n\n';
 			workerCode += funcBuildSingelton( 'LoaderBase', 'LoaderBase', LoaderBase );
 			workerCode += funcBuildObject( 'Consts', Consts );
-			workerCode += funcBuildObject( 'Validator', Validator );
-			workerCode += funcBuildSingelton( 'ConsoleLogger', 'ConsoleLogger', ConsoleLogger );
 			workerCode += funcBuildSingelton( 'Parser', 'Parser', Parser );
 			workerCode += funcBuildSingelton( 'RawMesh', 'RawMesh', RawMesh );
 			workerCode += funcBuildSingelton( 'RawMeshSubGroup', 'RawMeshSubGroup', RawMeshSubGroup );
@@ -278,7 +276,6 @@ THREE.OBJLoader2 = (function () {
 		}
 		this.workerSupport.run(
 			{
-				cmd: 'run',
 				params: {
 					useAsync: true,
 					materialPerSmoothingGroup: this.materialPerSmoothingGroup,
@@ -293,8 +290,9 @@ THREE.OBJLoader2 = (function () {
 					// in async case only material names are supplied to parser
 					materials: materialNames
 				},
-				buffers: {
-					input: content
+				data: {
+					input: content,
+					options: null
 				}
 			},
 			[ content.buffer ]
@@ -561,7 +559,7 @@ THREE.OBJLoader2 = (function () {
 							throw 'Vertex Colors were detected, but vertex count and color count do not match!';
 
 						}
-						this.processCompletedObject( null, this.rawMesh.groupName, currentByte );
+						this.processCompletedObject( this.rawMesh.objectName, this.rawMesh.groupName, currentByte );
 						reachedFaces = false;
 
 					}
@@ -600,20 +598,13 @@ THREE.OBJLoader2 = (function () {
 
 				case Consts.LINE_G:
 					this.processCompletedGroup( concatStringBuffer( buffer, bufferPointer, slashSpacePattern ), currentByte );
+					reachedFaces = false;
 					flushStringBuffer( buffer, bufferPointer );
 					break;
 
 				case Consts.LINE_O:
-					if ( this.rawMesh.vertices.length > 0 ) {
-
-						this.processCompletedObject( concatStringBuffer( buffer, bufferPointer, slashSpacePattern ), null, currentByte );
+					this.processCompletedObject( concatStringBuffer( buffer, bufferPointer, slashSpacePattern ), this.rawMesh.groupName, currentByte );
 						reachedFaces = false;
-
-					} else {
-
-						this.rawMesh.pushObject( concatStringBuffer( buffer, bufferPointer, slashSpacePattern ) );
-
-					}
 					flushStringBuffer( buffer, bufferPointer );
 					break;
 
@@ -656,9 +647,15 @@ THREE.OBJLoader2 = (function () {
 				this.buildMesh( result, currentByte );
 				var progressBytesPercent = currentByte / this.totalBytes;
 				this.callbackProgress( 'Completed object: ' + objectName + ' Total progress: ' + ( progressBytesPercent * 100 ).toFixed( 2 ) + '%', progressBytesPercent );
+			this.rawMesh = this.rawMesh.newInstanceFromObject( objectName, groupName );
+
+			} else {
+
+				// if a object was set that did not lead to object creation in finalize, then the object name has to be updated
+				this.rawMesh.pushObject( objectName );
 
 			}
-			this.rawMesh = this.rawMesh.newInstanceFromObject( objectName, groupName );
+
 		};
 
 		Parser.prototype.processCompletedGroup = function ( groupName, currentByte ) {

+ 6 - 5
examples/webgl_loader_obj2.html

@@ -139,14 +139,14 @@
 
 				OBJLoader2Example.prototype.initContent = function () {
 					var modelName = 'female02';
-					this._reportProgress( 'Loading: ' + modelName );
+					this._reportProgress( { detail: { text: 'Loading: ' + modelName } } );
 
 					var scope = this;
 					var objLoader = new THREE.OBJLoader2();
 					var callbackOnLoad = function ( event ) {
 						scope.scene.add( event.detail.loaderRootNode );
 						console.log( 'Loading complete: ' + event.detail.modelName );
-						scope._reportProgress( '' );
+						scope._reportProgress( { detail: { text: '' } } );
 					};
 
 					var onLoadMtl = function ( materials ) {
@@ -160,9 +160,10 @@
 					objLoader.loadMtl( 'obj/female02/female02.mtl', 'female02.mtl', null, onLoadMtl );
 				};
 
-				OBJLoader2Example.prototype._reportProgress = function( content ) {
-					console.log( 'Progress: ' + content );
-					document.getElementById( 'feedback' ).innerHTML = Validator.isValid( content ) ? content : '';
+				OBJLoader2Example.prototype._reportProgress = function( event ) {
+					var output = Validator.verifyInput( event.detail.text, '' );
+					console.log( 'Progress: ' + output );
+					document.getElementById( 'feedback' ).innerHTML = output;
 				};
 
 				OBJLoader2Example.prototype.resizeDisplayGL = function () {

+ 4 - 6
examples/webgl_loader_obj2_meshspray.html

@@ -140,10 +140,8 @@
 					var buildCode = function ( funcBuildObject, funcBuildSingelton ) {
 						var workerCode = '';
 						workerCode += '/**\n';
-						workerCode += '  * This code was constructed by MeshSpray buildWorkerCode.\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 );
 
 						return workerCode;
@@ -153,7 +151,6 @@
 					this.workerSupport.setCallbacks( scopeBuilderFunc, scopeFuncComplete );
 					this.workerSupport.run(
 						{
-							cmd: 'run',
 							params: {
 								dimension: prepData.dimension,
 								quantity: prepData.quantity,
@@ -166,8 +163,9 @@
 								debug: this.logger.debug,
 								enabled: this.logger.enabled
 							},
-							buffers: {
-								input: null
+							data: {
+								input: null,
+								options: null
 							}
 						}
 					);

+ 0 - 2
src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl

@@ -1,5 +1,3 @@
-#define saturate(a) clamp( a, 0.0, 1.0 )
-
 uniform float toneMappingExposure;
 uniform float toneMappingWhitePoint;
 

+ 2 - 0
src/textures/VideoTexture.js

@@ -14,6 +14,8 @@ function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, forma
 
 	function update() {
 
+		var video = scope.image;
+
 		if ( video.readyState >= video.HAVE_CURRENT_DATA ) {
 
 			scope.needsUpdate = true;