2
0
Эх сурвалжийг харах

Introduce GLTFLoader plugin system

Takahiro 5 жил өмнө
parent
commit
dc390fc70c

+ 119 - 20
examples/js/loaders/GLTFLoader.js

@@ -15,6 +15,9 @@ THREE.GLTFLoader = ( function () {
 		this.dracoLoader = null;
 		this.ddsLoader = null;
 
+		this.plugins = [];
+		this.register( GLTFMaterialsClearcoatExtension );
+
 	}
 
 	GLTFLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {
@@ -110,6 +113,26 @@ THREE.GLTFLoader = ( function () {
 
 		},
 
+		register: function ( plugin ) {
+
+			if ( ! this.plugins.includes( plugin ) ) {
+
+				this.plugins.push( plugin );
+
+			}
+
+		},
+
+		unregister: function ( plugin ) {
+
+			if ( this.plugins.includes( plugin ) ) {
+
+				this.plugins.splice( this.plugins.indexOf( plugin ), 1 );
+
+			}
+
+		},
+
 		parse: function ( data, path, onLoad, onError ) {
 
 			var content;
@@ -168,10 +191,6 @@ THREE.GLTFLoader = ( function () {
 							extensions[ extensionName ] = new GLTFLightsExtension( json );
 							break;
 
-						case EXTENSIONS.KHR_MATERIALS_CLEARCOAT:
-							extensions[ extensionName ] = new GLTFMaterialsClearcoatExtension();
-							break;
-
 						case EXTENSIONS.KHR_MATERIALS_UNLIT:
 							extensions[ extensionName ] = new GLTFMaterialsUnlitExtension();
 							break;
@@ -217,7 +236,7 @@ THREE.GLTFLoader = ( function () {
 				manager: this.manager
 
 			} );
-
+			parser.setPlugins( this.plugins );
 			parser.parse( onLoad, onError );
 
 		}
@@ -418,8 +437,9 @@ THREE.GLTFLoader = ( function () {
 	 *
 	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_clearcoat
 	 */
-	function GLTFMaterialsClearcoatExtension() {
+	function GLTFMaterialsClearcoatExtension( parser ) {
 
+		this.parser = parser;
 		this.name = EXTENSIONS.KHR_MATERIALS_CLEARCOAT;
 
 	}
@@ -430,7 +450,16 @@ THREE.GLTFLoader = ( function () {
 
 	};
 
-	GLTFMaterialsClearcoatExtension.prototype.extendParams = function ( materialParams, materialDef, parser ) {
+	GLTFMaterialsClearcoatExtension.prototype.extendMaterialParams = function ( materialIndex, materialParams ) {
+
+		var parser = this.parser;
+		var materialDef = parser.json.materials[ materialIndex ];
+
+		if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
+
+			return Promise.resolve();
+
+		}
 
 		var pending = [];
 
@@ -1399,6 +1428,7 @@ THREE.GLTFLoader = ( function () {
 
 		this.json = json || {};
 		this.extensions = extensions || {};
+		this.plugins = {};
 		this.options = options || {};
 
 		// loader object cache
@@ -1421,6 +1451,23 @@ THREE.GLTFLoader = ( function () {
 
 	}
 
+	GLTFParser.prototype.setPlugins = function ( pluginList ) {
+
+		for ( var i = 0; i < pluginList.length; i ++ ) {
+
+			var plugin = new pluginList[ i ]( this );
+			this.plugins[ plugin.name ] = plugin;
+
+			// Workaround to avoid determining as unknown extension
+			// in addUnknownExtensionsToUserData().
+			// Remove this workaround if we move all the existing
+			// extension handlers to plugin system
+			this.extensions[ plugin.name ] = true;
+
+		}
+
+	};
+
 	GLTFParser.prototype.parse = function ( onLoad, onError ) {
 
 		var parser = this;
@@ -1524,6 +1571,38 @@ THREE.GLTFLoader = ( function () {
 
 	};
 
+	GLTFParser.prototype._invokeOne = function ( func ) {
+
+		var extensions = Object.values( this.plugins );
+		extensions.push( this );
+
+		for ( var i = 0; i < extensions.length; i ++ ) {
+
+			var result = func( extensions[ i ] );
+
+			if ( result ) return result;
+
+		}
+
+	};
+
+	GLTFParser.prototype._invokeAll = function ( func ) {
+
+		var extensions = Object.values( this.plugins );
+		extensions.unshift( this );
+
+		var pending = [];
+
+		for ( var i = 0; i < extensions.length; i ++ ) {
+
+			pending.push( func( extensions[ i ] ) );
+
+		}
+
+		return Promise.all( pending );
+
+	};
+
 	/**
 	 * Requests the specified dependency asynchronously, with caching.
 	 * @param {string} type
@@ -1548,7 +1627,11 @@ THREE.GLTFLoader = ( function () {
 					break;
 
 				case 'mesh':
-					dependency = this.loadMesh( index );
+					dependency = this._invokeOne( function ( ext ) {
+
+						return ext.loadMesh && ext.loadMesh( index );
+
+					} );
 					break;
 
 				case 'accessor':
@@ -1556,7 +1639,11 @@ THREE.GLTFLoader = ( function () {
 					break;
 
 				case 'bufferView':
-					dependency = this.loadBufferView( index );
+					dependency = this._invokeOne( function ( ext ) {
+
+						return ext.loadBufferView && ext.loadBufferView( index );
+
+					} );
 					break;
 
 				case 'buffer':
@@ -1564,7 +1651,11 @@ THREE.GLTFLoader = ( function () {
 					break;
 
 				case 'material':
-					dependency = this.loadMaterial( index );
+					dependency = this._invokeOne( function ( ext ) {
+
+						return ext.loadMaterial && ext.loadMaterial( index );
+
+					} );
 					break;
 
 				case 'texture':
@@ -2093,6 +2184,12 @@ THREE.GLTFLoader = ( function () {
 
 	};
 
+	GLTFParser.prototype.getMaterialType = function () {
+
+		return THREE.MeshStandardMaterial;
+
+	};
+
 	/**
 	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#materials
 	 * @param {number} materialIndex
@@ -2128,8 +2225,6 @@ THREE.GLTFLoader = ( function () {
 			// Specification:
 			// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material
 
-			materialType = THREE.MeshStandardMaterial;
-
 			var metallicRoughness = materialDef.pbrMetallicRoughness || {};
 
 			materialParams.color = new THREE.Color( 1.0, 1.0, 1.0 );
@@ -2160,6 +2255,18 @@ THREE.GLTFLoader = ( function () {
 
 			}
 
+			materialType = this._invokeOne( function ( ext ) {
+
+				return ext.getMaterialType && ext.getMaterialType();
+
+			} );
+
+			pending.push( this._invokeAll( function ( ext ) {
+
+				return ext.extendMaterialParams && ext.extendMaterialParams( materialIndex, materialParams );
+
+			} ) );
+
 		}
 
 		if ( materialDef.doubleSided === true ) {
@@ -2227,14 +2334,6 @@ THREE.GLTFLoader = ( function () {
 
 		}
 
-		if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_CLEARCOAT ] ) {
-
-			var clearcoatExtension = extensions[ EXTENSIONS.KHR_MATERIALS_CLEARCOAT ];
-			materialType = clearcoatExtension.getMaterialType();
-			pending.push( clearcoatExtension.extendParams( materialParams, { extensions: materialExtensions }, parser ) );
-
-		}
-
 		return Promise.all( pending ).then( function () {
 
 			var material;

+ 119 - 20
examples/jsm/loaders/GLTFLoader.js

@@ -79,6 +79,9 @@ var GLTFLoader = ( function () {
 		this.dracoLoader = null;
 		this.ddsLoader = null;
 
+		this.plugins = [];
+		this.register( GLTFMaterialsClearcoatExtension );
+
 	}
 
 	GLTFLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
@@ -174,6 +177,26 @@ var GLTFLoader = ( function () {
 
 		},
 
+		register: function ( plugin ) {
+
+			if ( ! this.plugins.includes( plugin ) ) {
+
+				this.plugins.push( plugin );
+
+			}
+
+		},
+
+		unregister: function ( plugin ) {
+
+			if ( this.plugins.includes( plugin ) ) {
+
+				this.plugins.splice( this.plugins.indexOf( plugin ), 1 );
+
+			}
+
+		},
+
 		parse: function ( data, path, onLoad, onError ) {
 
 			var content;
@@ -232,10 +255,6 @@ var GLTFLoader = ( function () {
 							extensions[ extensionName ] = new GLTFLightsExtension( json );
 							break;
 
-						case EXTENSIONS.KHR_MATERIALS_CLEARCOAT:
-							extensions[ extensionName ] = new GLTFMaterialsClearcoatExtension();
-							break;
-
 						case EXTENSIONS.KHR_MATERIALS_UNLIT:
 							extensions[ extensionName ] = new GLTFMaterialsUnlitExtension();
 							break;
@@ -281,7 +300,7 @@ var GLTFLoader = ( function () {
 				manager: this.manager
 
 			} );
-
+			parser.setPlugins( this.plugins );
 			parser.parse( onLoad, onError );
 
 		}
@@ -482,8 +501,9 @@ var GLTFLoader = ( function () {
 	 *
 	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_clearcoat
 	 */
-	function GLTFMaterialsClearcoatExtension() {
+	function GLTFMaterialsClearcoatExtension( parser ) {
 
+		this.parser = parser;
 		this.name = EXTENSIONS.KHR_MATERIALS_CLEARCOAT;
 
 	}
@@ -494,7 +514,16 @@ var GLTFLoader = ( function () {
 
 	};
 
-	GLTFMaterialsClearcoatExtension.prototype.extendParams = function ( materialParams, materialDef, parser ) {
+	GLTFMaterialsClearcoatExtension.prototype.extendMaterialParams = function ( materialIndex, materialParams ) {
+
+		var parser = this.parser;
+		var materialDef = parser.json.materials[ materialIndex ];
+
+		if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
+
+			return Promise.resolve();
+
+		}
 
 		var pending = [];
 
@@ -1463,6 +1492,7 @@ var GLTFLoader = ( function () {
 
 		this.json = json || {};
 		this.extensions = extensions || {};
+		this.plugins = {};
 		this.options = options || {};
 
 		// loader object cache
@@ -1485,6 +1515,23 @@ var GLTFLoader = ( function () {
 
 	}
 
+	GLTFParser.prototype.setPlugins = function ( pluginList ) {
+
+		for ( var i = 0; i < pluginList.length; i ++ ) {
+
+			var plugin = new pluginList[ i ]( this );
+			this.plugins[ plugin.name ] = plugin;
+
+			// Workaround to avoid determining as unknown extension
+			// in addUnknownExtensionsToUserData().
+			// Remove this workaround if we move all the existing
+			// extension handlers to plugin system
+			this.extensions[ plugin.name ] = true;
+
+		}
+
+	};
+
 	GLTFParser.prototype.parse = function ( onLoad, onError ) {
 
 		var parser = this;
@@ -1588,6 +1635,38 @@ var GLTFLoader = ( function () {
 
 	};
 
+	GLTFParser.prototype._invokeOne = function ( func ) {
+
+		var extensions = Object.values( this.plugins );
+		extensions.push( this );
+
+		for ( var i = 0; i < extensions.length; i ++ ) {
+
+			var result = func( extensions[ i ] );
+
+			if ( result ) return result;
+
+		}
+
+	};
+
+	GLTFParser.prototype._invokeAll = function ( func ) {
+
+		var extensions = Object.values( this.plugins );
+		extensions.unshift( this );
+
+		var pending = [];
+
+		for ( var i = 0; i < extensions.length; i ++ ) {
+
+			pending.push( func( extensions[ i ] ) );
+
+		}
+
+		return Promise.all( pending );
+
+	};
+
 	/**
 	 * Requests the specified dependency asynchronously, with caching.
 	 * @param {string} type
@@ -1612,7 +1691,11 @@ var GLTFLoader = ( function () {
 					break;
 
 				case 'mesh':
-					dependency = this.loadMesh( index );
+					dependency = this._invokeOne( function ( ext ) {
+
+						return ext.loadMesh && ext.loadMesh( index );
+
+					} );
 					break;
 
 				case 'accessor':
@@ -1620,7 +1703,11 @@ var GLTFLoader = ( function () {
 					break;
 
 				case 'bufferView':
-					dependency = this.loadBufferView( index );
+					dependency = this._invokeOne( function ( ext ) {
+
+						return ext.loadBufferView && ext.loadBufferView( index );
+
+					} );
 					break;
 
 				case 'buffer':
@@ -1628,7 +1715,11 @@ var GLTFLoader = ( function () {
 					break;
 
 				case 'material':
-					dependency = this.loadMaterial( index );
+					dependency = this._invokeOne( function ( ext ) {
+
+						return ext.loadMaterial && ext.loadMaterial( index );
+
+					} );
 					break;
 
 				case 'texture':
@@ -2157,6 +2248,12 @@ var GLTFLoader = ( function () {
 
 	};
 
+	GLTFParser.prototype.getMaterialType = function () {
+
+		return MeshStandardMaterial;
+
+	};
+
 	/**
 	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#materials
 	 * @param {number} materialIndex
@@ -2192,8 +2289,6 @@ var GLTFLoader = ( function () {
 			// Specification:
 			// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material
 
-			materialType = MeshStandardMaterial;
-
 			var metallicRoughness = materialDef.pbrMetallicRoughness || {};
 
 			materialParams.color = new Color( 1.0, 1.0, 1.0 );
@@ -2224,6 +2319,18 @@ var GLTFLoader = ( function () {
 
 			}
 
+			materialType = this._invokeOne( function ( ext ) {
+
+				return ext.getMaterialType && ext.getMaterialType();
+
+			} );
+
+			pending.push( this._invokeAll( function ( ext ) {
+
+				return ext.extendMaterialParams && ext.extendMaterialParams( materialIndex, materialParams );
+
+			} ) );
+
 		}
 
 		if ( materialDef.doubleSided === true ) {
@@ -2291,14 +2398,6 @@ var GLTFLoader = ( function () {
 
 		}
 
-		if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_CLEARCOAT ] ) {
-
-			var clearcoatExtension = extensions[ EXTENSIONS.KHR_MATERIALS_CLEARCOAT ];
-			materialType = clearcoatExtension.getMaterialType();
-			pending.push( clearcoatExtension.extendParams( materialParams, { extensions: materialExtensions }, parser ) );
-
-		}
-
 		return Promise.all( pending ).then( function () {
 
 			var material;