浏览代码

OBJLoader2 V2.1.0:
- Builder enhancements:
- Materials can be added to it as regular objects, as jsonified objects (e.g. from worker) and as clone instruction (map of property and value)
- Separated mesh processing from material processing
- Builder no longer defines default materials. This is no the responsibility of the user (loader)
- WorkerSupport is now able to load arbitrary js files into Blob used to create the Worker (as exemplary shown and used in MeshSpray)
- Updated documentation

Kai Salmen 7 年之前
父节点
当前提交
3fbe20c7e9

+ 51 - 11
docs/examples/loaders/LoaderSupport.html

@@ -20,7 +20,7 @@
 		[page:LoaderSupport.WorkerRunnerRefImpl]<br>
 		[page:LoaderSupport.WorkerDirector]<br>
 		[page:LoaderSupport.PrepData]<br>
-		[page:LoaderSupport.Commons]<br>
+		[page:LoaderSupport.LoaderBase]<br>
 		[page:LoaderSupport.Callbacks]<br>
 		[page:LoaderSupport.Validator]<br>
 		[page:LoaderSupport.ConsoleLogger]
@@ -54,12 +54,50 @@
 		</div>
 
 
-		<h3>[method:Array buildMeshes] (Object payload)</h3>
+		<h3>[method:Array processPayload] ( Object payload )</h3>
 		<div>
-			[page:Object payload] - Raw mesh description (buffers, params, materials) used to build one to many meshes.
+			[page:Object payload] - Raw Mesh or Material descriptions.
+		</div>
+		<div>
+			Delegates processing of the payload (mesh building or material update) to the corresponding functions (BW-compatibility).
 		</div>
+		<br>
+		<br>
+
+
+		<h3>[method:Array buildMeshes] ( Object meshPayload )</h3>
+		<div>
+			[page:Object meshPayload] - Raw mesh description (buffers, params, materials) used to build one to many meshes.
+		</div>
+		<div>
+			Builds one or multiple meshes from the data described in the payload (buffers, params, material info).
+		</div>
+		<br>
+		<br>
+
+
+		<h3>[method:null updateMaterials] ( Object materialPayload )</h3>
+		<div>
+			[page:Object materialPayload] - Material update instructions
+		</div>
+		<div>
+			Updates the materials with contained material objects (sync) or from alteration instructions (async).
+		</div>
+		<br>
+		<br>
+
+
+		<h3>[method:Object getMaterialsJSON] ()</h3>
+		<div>
+			Returns the mapping object of material name and corresponding jsonified material.
+		</div>
+		<br>
+		<br>
+
+
+		<h3>[method:Object getMaterials] ()</h3>
 		<div>
-			Builds one or multiple meshes from the data described in the payload (buffers, params, material info.
+			Returns the mapping object of material name and corresponding material.
 		</div>
 		<br>
 		<br>
@@ -118,10 +156,12 @@
 
 		<h2>Methods</h2>
 
-		<h3>[method:null validate] ( [page:Function functionCodeBuilder], [page:Boolean forceWorkerReload], [page:LoaderSupport.WorkerRunnerRefImpl runnerImpl] )</h3>
+		<h3>[method:null validate] ( [page:Function functionCodeBuilder], [page:Boolean forceWorkerReload], 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.
-			[page:Boolean forceWorkerReload] - Force re-build of the worker code.
+			[page:Function functionCodeBuilder] - Function that is invoked with funcBuildObject and funcBuildSingelton that allows stringification of objects and singletons.<br>
+			[page:Boolean forceWorkerReload] - Force re-build of the worker code.<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.
 		</div>
 		<div>
@@ -146,7 +186,7 @@
 
 		<h3>[method:null setCallbacks] ( [page:Function builder], [page:Function onLoad] )</h3>
 		<div>
-			[page:Function builder] - The builder function. Default is [page:LoaderSupport.Builder].
+			[page:Function builder] - The builder function. Default is [page:LoaderSupport.Builder].<br>
 			[page:Function onLoad] - The function that is called when parsing is complete.
 		</div>
 		<div>
@@ -178,7 +218,7 @@
 
 		<h3>[method:null applyProperties] ( [page:Object parser], [page:Object params] )</h3>
 		<div>
-			[page:Object parser] - The parser instance
+			[page:Object parser] - The parser instance<br>
 			[page:Object params] - The parameter object
 		</div>
 		<div>
@@ -355,10 +395,10 @@
 		<br>
 
 
-		<a name="Commons"></a><h1>Commons</h1>
+		<a name="LoaderBase"></a><h1>LoaderBase</h1>
 		<h2>Constructor</h2>
 
-		<h3>Commons( [page:LoaderSupport.ConsoleLogger logger], [page:LoadingManager manager] )</h3>
+		<h3>LoaderBase( [page:LoaderSupport.ConsoleLogger logger], [page:LoadingManager manager] )</h3>
 		<div>
 			[page:LoaderSupport.ConsoleLogger logger] - logger to be used
 			[page:LoadingManager manager] - The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].

文件差异内容过多而无法显示
+ 482 - 370
examples/js/loaders/LoaderSupport.js


+ 84 - 35
examples/js/loaders/OBJLoader2.js

@@ -15,16 +15,16 @@ if ( THREE.OBJLoader2 === undefined ) { THREE.OBJLoader2 = {} }
  */
 THREE.OBJLoader2 = (function () {
 
-	var OBJLOADER2_VERSION = '2.0.1';
-	var Commons = THREE.LoaderSupport.Commons;
+	var OBJLOADER2_VERSION = '2.1.0';
+	var LoaderBase = THREE.LoaderSupport.LoaderBase;
 	var Validator = THREE.LoaderSupport.Validator;
 	var ConsoleLogger = THREE.LoaderSupport.ConsoleLogger;
 
-	OBJLoader2.prototype = Object.create( THREE.LoaderSupport.Commons.prototype );
+	OBJLoader2.prototype = Object.create( THREE.LoaderSupport.LoaderBase.prototype );
 	OBJLoader2.prototype.constructor = OBJLoader2;
 
 	function OBJLoader2( logger, manager ) {
-		THREE.LoaderSupport.Commons.call( this, logger, manager );
+		THREE.LoaderSupport.LoaderBase.call( this, logger, manager );
 		this.logger.logInfo( 'Using THREE.OBJLoader2 version: ' + OBJLOADER2_VERSION );
 
 		this.materialPerSmoothingGroup = false;
@@ -156,7 +156,7 @@ THREE.OBJLoader2 = (function () {
 	};
 
 	OBJLoader2.prototype._applyPrepData = function ( prepData ) {
-		THREE.LoaderSupport.Commons.prototype._applyPrepData.call( this, prepData );
+		THREE.LoaderSupport.LoaderBase.prototype._applyPrepData.call( this, prepData );
 
 		if ( Validator.isValid( prepData ) ) {
 
@@ -178,11 +178,12 @@ THREE.OBJLoader2 = (function () {
 		parser.setMaterialPerSmoothingGroup( this.materialPerSmoothingGroup );
 		parser.setUseIndices( this.useIndices );
 		parser.setDisregardNormals( this.disregardNormals );
-		parser.setMaterialNames( this.builder.materialNames );
+		// sync code works directly on the material references
+		parser.setMaterials( this.builder.getMaterials() );
 
 		var scope = this;
 		var onMeshLoaded = function ( payload ) {
-			var meshes = scope.builder.buildMeshes( payload );
+			var meshes = scope.builder.processPayload( payload );
 			var mesh;
 			for ( var i in meshes ) {
 				mesh = meshes[ i ];
@@ -240,7 +241,7 @@ THREE.OBJLoader2 = (function () {
 			scope.logger.logTimeEnd( 'OBJLoader2 parseAsync: ' + scope.modelName );
 		};
 		var scopedOnMeshLoaded = function ( payload ) {
-			var meshes = scope.builder.buildMeshes( payload );
+			var meshes = scope.builder.processPayload( payload );
 			var mesh;
 			for ( var i in meshes ) {
 				mesh = meshes[ i ];
@@ -254,7 +255,7 @@ THREE.OBJLoader2 = (function () {
 			workerCode += '/**\n';
 			workerCode += '  * This code was constructed by OBJLoader2 buildWorkerCode.\n';
 			workerCode += '  */\n\n';
-			workerCode += funcBuildSingelton( 'Commons', 'Commons', Commons );
+			workerCode += funcBuildSingelton( 'LoaderBase', 'LoaderBase', LoaderBase );
 			workerCode += funcBuildObject( 'Consts', Consts );
 			workerCode += funcBuildObject( 'Validator', Validator );
 			workerCode += funcBuildSingelton( 'ConsoleLogger', 'ConsoleLogger', ConsoleLogger );
@@ -266,10 +267,19 @@ THREE.OBJLoader2 = (function () {
 		};
 		this.workerSupport.validate( buildCode, false );
 		this.workerSupport.setCallbacks( scopedOnMeshLoaded, scopedOnLoad );
+
+		var materialNames = {};
+		var materials = this.builder.getMaterials();
+		for ( var materialName in materials ) {
+
+			materialNames[ materialName ] = materialName;
+
+		}
 		this.workerSupport.run(
 			{
 				cmd: 'run',
 				params: {
+					useAsync: true,
 					materialPerSmoothingGroup: this.materialPerSmoothingGroup,
 					useIndices: this.useIndices,
 					disregardNormals: this.disregardNormals
@@ -279,7 +289,8 @@ THREE.OBJLoader2 = (function () {
 					enabled: this.logger.enabled
 				},
 				materials: {
-					materialNames: this.builder.materialNames
+					// in async case only material names are supplied to parser
+					materials: materialNames
 				},
 				buffers: {
 					input: content
@@ -323,8 +334,9 @@ THREE.OBJLoader2 = (function () {
 			this.callbackProgress = null;
 			this.callbackBuilder = null;
 
-			this.materialNames = [];
+			this.materials = {};
 			this.rawMesh = null;
+			this.useAsync = false;
 			this.materialPerSmoothingGroup = false;
 			this.useIndices = false;
 			this.disregardNormals = false;
@@ -340,6 +352,10 @@ THREE.OBJLoader2 = (function () {
 			this.totalBytes = 0;
 		};
 
+		Parser.prototype.setUseAsync = function ( useAsync ) {
+			this.useAsync = useAsync;
+		};
+
 		Parser.prototype.setMaterialPerSmoothingGroup = function ( materialPerSmoothingGroup ) {
 			this.materialPerSmoothingGroup = materialPerSmoothingGroup;
 		};
@@ -352,9 +368,9 @@ THREE.OBJLoader2 = (function () {
 			this.disregardNormals = disregardNormals;
 		};
 
-		Parser.prototype.setMaterialNames = function ( materialNames ) {
-			this.materialNames = Validator.verifyInput( materialNames, this.materialNames );
-			this.materialNames = Validator.verifyInput( this.materialNames, [] );
+		Parser.prototype.setMaterials = function ( materials ) {
+			this.materials = Validator.verifyInput( materials, this.materials );
+			this.materials = Validator.verifyInput( this.materials, {} );
 		};
 
 		Parser.prototype.setCallbackBuilder = function ( callbackBuilder ) {
@@ -371,9 +387,11 @@ THREE.OBJLoader2 = (function () {
 
 			if ( this.logger.isEnabled() ) {
 
-				var matNames = ( this.materialNames.length > 0 ) ? '\n\tmaterialNames:\n\t\t- ' + this.materialNames.join( '\n\t\t- ' ) : '\n\tmaterialNames: None';
+				var matKeys = Object.keys( this.materials );
+				var matNames = ( matKeys.length > 0 ) ? '\n\tmaterialNames:\n\t\t- ' + matKeys.join( '\n\t\t- ' ) : '\n\tmaterialNames: None';
 				var printedConfig = 'OBJLoader2.Parser configuration:'
 						+ matNames
+						+ '\n\tuseAsync: ' + this.useAsync
 						+ '\n\tmaterialPerSmoothingGroup: ' + this.materialPerSmoothingGroup
 						+ '\n\tuseIndices: ' + this.useIndices
 						+ '\n\tdisregardNormals: ' + this.disregardNormals
@@ -702,10 +720,10 @@ THREE.OBJLoader2 = (function () {
 			var colorFA = ( result.absoluteColorCount > 0 ) ? new Float32Array( result.absoluteColorCount ) : null;
 			var normalFA = ( result.absoluteNormalCount > 0 ) ? new Float32Array( result.absoluteNormalCount ) : null;
 			var uvFA = ( result.absoluteUvCount > 0 ) ? new Float32Array( result.absoluteUvCount ) : null;
+			var haveVertexColors = Validator.isValid( colorFA );
 
 			var rawObjectDescription;
-			var materialDescription;
-			var materialDescriptions = [];
+			var materialNames = [];
 
 			var createMultiMaterial = ( rawObjectDescriptions.length > 1 );
 			var materialIndex = 0;
@@ -722,36 +740,68 @@ THREE.OBJLoader2 = (function () {
 			var materialGroupOffset = 0;
 			var materialGroupLength = 0;
 
+			var materialOrg, material, materialName, materialNameOrg;
 			for ( var oodIndex in rawObjectDescriptions ) {
+
 				if ( ! rawObjectDescriptions.hasOwnProperty( oodIndex ) ) continue;
 				rawObjectDescription = rawObjectDescriptions[ oodIndex ];
 
-				materialDescription = {
-					name: rawObjectDescription.materialName,
-					flat: false,
-					default: false
-				};
-				if ( this.materialNames[ materialDescription.name ] === null ) {
+				materialNameOrg = rawObjectDescription.materialName;
+				materialName = materialNameOrg + ( haveVertexColors ? '_vertexColor' : '' ) + ( rawObjectDescription.smoothingGroup === 0 ? '_flat' : '' );
+				materialOrg = this.materials[ materialNameOrg ];
+				material = this.materials[ materialName ];
+
+				// both original and derived names do not lead to an existing material => need to use a default material
+				if ( ! Validator.isValid( materialOrg ) && ! Validator.isValid( material ) ) {
 
-					materialDescription.default = true;
+					var defaultMaterialName = haveVertexColors ? 'vertexColorMaterial' : 'defaultMaterial';
+					materialOrg = this.materials[ defaultMaterialName ];
 					this.logger.logWarn( 'object_group "' + rawObjectDescription.objectName + '_' +
-						rawObjectDescription.groupName +
-						'" was defined without material! Assigning "defaultMaterial".' );
+						rawObjectDescription.groupName + '" was defined with unresolvable material "' +
+						materialNameOrg + '"! Assigning "' + defaultMaterialName + '".' );
+					materialNameOrg = defaultMaterialName;
+
+					// if names are identical then there is no need for later manipulation
+					if ( materialNameOrg === materialName ) {
+
+						material = materialOrg;
+						materialName = defaultMaterialName;
+
+					}
+
+				}
+				if ( ! Validator.isValid( material ) ) {
+
+					var materialCloneInstructions = {
+						materialNameOrg: materialNameOrg,
+						materialName: materialName,
+						materialProperties: {
+							vertexColors: haveVertexColors ? 2 : 0,
+							flatShading: rawObjectDescription.smoothingGroup === 0
+						}
+					};
+					var payload = {
+						cmd: 'materialData',
+						materials: {
+							materialCloneInstructions: materialCloneInstructions
+						}
+					};
+					this.callbackBuilder( payload );
+
+					// fake entry for async; sync Parser always works on material references (Builder update directly visible here)
+					if ( this.useAsync ) this.materials[ materialName ] = materialCloneInstructions;
 
 				}
-				// Attach '_flat' to materialName in case flat shading is needed due to smoothingGroup 0
-				if ( rawObjectDescription.smoothingGroup === 0 ) materialDescription.flat = true;
 
 				if ( createMultiMaterial ) {
 
 					// re-use material if already used before. Reduces materials array size and eliminates duplicates
-
-					selectedMaterialIndex = materialIndexMapping[ materialDescription.name ];
+					selectedMaterialIndex = materialIndexMapping[ materialName ];
 					if ( ! selectedMaterialIndex ) {
 
 						selectedMaterialIndex = materialIndex;
-						materialIndexMapping[ materialDescription.name ] = materialIndex;
-						materialDescriptions.push( materialDescription );
+						materialIndexMapping[ materialName ] = materialIndex;
+						materialNames.push( materialName );
 						materialIndex++;
 
 					}
@@ -766,7 +816,7 @@ THREE.OBJLoader2 = (function () {
 
 				} else {
 
-					materialDescriptions.push( materialDescription );
+					materialNames.push( materialName );
 
 				}
 
@@ -816,7 +866,6 @@ THREE.OBJLoader2 = (function () {
 					this.logger.logDebug( createdReport );
 				}
 
-
 			}
 
 			this.outputObjectCount++;
@@ -831,7 +880,7 @@ THREE.OBJLoader2 = (function () {
 					},
 					materials: {
 						multiMaterial: createMultiMaterial,
-						materialDescriptions: materialDescriptions,
+						materialNames: materialNames,
 						materialGroups: materialGroups
 					},
 					buffers: {

+ 45 - 26
examples/webgl_loader_obj2_meshspray.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>Mesh Spray - Worker based mesh spray</title>
+		<title>three.js webgl - Mesh Spray</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 
@@ -88,11 +88,11 @@
 				var Validator = THREE.LoaderSupport.Validator;
 				var ConsoleLogger = THREE.LoaderSupport.ConsoleLogger;
 
-				MeshSpray.prototype = Object.create( THREE.LoaderSupport.Commons.prototype );
+				MeshSpray.prototype = Object.create( THREE.LoaderSupport.LoaderBase.prototype );
 				MeshSpray.prototype.constructor = MeshSpray;
 
 				function MeshSpray( manager ) {
-					THREE.LoaderSupport.Commons.call( this, manager );
+					THREE.LoaderSupport.LoaderBase.call( this, manager );
 					this.workerSupport = null;
 					this.logger = new ConsoleLogger();
 				};
@@ -116,7 +116,7 @@
 
 					var scope = this;
 					var scopeBuilderFunc = function ( payload ) {
-						var meshes = scope.builder.buildMeshes( payload );
+						var meshes = scope.builder.processPayload( payload );
 						var mesh;
 						for ( var i in meshes ) {
 							mesh = meshes[ i ];
@@ -148,25 +148,24 @@
 
 						return workerCode;
 					};
-					this.workerSupport.validate( buildCode, false );
+					var libs2Load = [ 'build/three.min.js' ];
+					this.workerSupport.validate( buildCode, false, libs2Load, '../' );
 					this.workerSupport.setCallbacks( scopeBuilderFunc, scopeFuncComplete );
 					this.workerSupport.run(
 						{
 							cmd: 'run',
 							params: {
-								debug: this.debug,
-								enableLogging: this.logger.enabled,
 								dimension: prepData.dimension,
 								quantity: prepData.quantity,
 								globalObjectCount: prepData.globalObjectCount
 							},
+							materials: {
+								serializedMaterials: this.builder.getMaterialsJSON()
+							},
 							logger: {
 								debug: this.logger.debug,
 								enabled: this.logger.enabled
 							},
-							materials: {
-								materialNames: this.builder.materialNames
-							},
 							buffers: {
 								input: null
 							}
@@ -185,21 +184,10 @@
 						this.quantity = 1;
 						this.callbackBuilder = null;
 						this.logger = logger;
+						this.serializedMaterials = null;
 					};
 
 					Parser.prototype.parse = function () {
-						var materialDescription;
-						var materialDescriptions = [];
-						var materialGroups = [];
-
-						materialDescription = {
-							name: 'Gen',
-							flat: false,
-							vertexColors: true,
-							default: true
-						};
-						materialDescriptions.push( materialDescription );
-
 						var baseTriangle = [ 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 0.0, -1.0, 1.0 ];
 						var vertices = [];
 						var colors = [];
@@ -263,6 +251,30 @@
 
 						}
 
+						/*
+						 * This demonstrates the usage of embedded three.js in the worker blob and
+						 * the serialization of materials back to the Builder outside the worker.
+						 *
+						 * This is not the most effective way, but outlining possibilities
+						 */
+						var materialName = 'vertexColorMaterial_double';
+						var vertexColorMaterialJson = this.serializedMaterials[ 'vertexColorMaterial' ];
+						var loader = new THREE.MaterialLoader();
+
+						var vertexColorMaterialDouble = loader.parse( vertexColorMaterialJson );
+						vertexColorMaterialDouble.name = materialName;
+						vertexColorMaterialDouble.side = THREE.DoubleSide;
+
+						var newSerializedMaterials = {};
+						newSerializedMaterials[ materialName ] = vertexColorMaterialDouble.toJSON();
+						var payload = {
+							cmd: 'materialData',
+							materials: {
+								serializedMaterials: newSerializedMaterials
+							}
+						};
+						this.callbackBuilder( payload );
+
 						this.globalObjectCount++;
 						this.callbackBuilder(
 							{
@@ -275,8 +287,8 @@
 								},
 								materials: {
 									multiMaterial: false,
-									materialDescriptions: materialDescriptions,
-									materialGroups: materialGroups
+									materialNames: [ materialName ],
+									materialGroups: []
 								},
 								buffers: {
 									vertices: vertexFA,
@@ -297,14 +309,21 @@
 					return Parser;
 				})();
 
+
+				Parser.prototype.setSerializedMaterials = function ( serializedMaterials ) {
+					if ( Validator.isValid( serializedMaterials ) ) {
+
+						this.serializedMaterials = serializedMaterials;
+
+					}
+				};
+
 				return MeshSpray;
 
 			})();
 
 			var MeshSprayApp = (function () {
 
-				var Validator = THREE.LoaderSupport.Validator;
-
 				function MeshSprayApp( elementToBindTo ) {
 					this.renderer = null;
 					this.canvas = elementToBindTo;

部分文件因为文件数量过多而无法显示