Browse Source

Merge pull request #13826 from donmccurdy/feat-gltf-extensions

GLTFLoader: Preserve unknown extension data on nodes and materials.
Mr.doob 7 years ago
parent
commit
99d02c8add
2 changed files with 76 additions and 19 deletions
  1. 22 0
      docs/examples/loaders/GLTFLoader.html
  2. 54 19
      examples/js/loaders/GLTFLoader.js

+ 22 - 0
docs/examples/loaders/GLTFLoader.html

@@ -84,6 +84,28 @@
 		<a href="https://github.com/stefanpenner/es6-promise">include a polyfill</a>
 		<a href="https://github.com/stefanpenner/es6-promise">include a polyfill</a>
 		providing a Promise replacement.</p>
 		providing a Promise replacement.</p>
 
 
+		<h2>Custom extensions</h2>
+
+		<p>
+			Metadata from unknown extensions is preserved as “.userData.gltfExtensions” on Object3D, Scene, and Material instances,
+			or attached to the response “gltf” object. Example:
+		</p>
+
+		<code>
+		loader.load('foo.gltf', function ( gltf ) {
+
+			var scene = gltf.scene;
+
+			var mesh = scene.children[ 3 ];
+
+			var fooExtension = mesh.userData.gltfExtensions.EXT_foo;
+
+			gltf.parser.getDependency( 'bufferView', fooExtension.bufferView )
+				.then( function ( fooBuffer ) { ... } );
+
+		} );
+		</code>
+
 		<br>
 		<br>
 		<hr>
 		<hr>
 
 

+ 54 - 19
examples/js/loaders/GLTFLoader.js

@@ -123,33 +123,42 @@ THREE.GLTFLoader = ( function () {
 
 
 			if ( json.extensionsUsed ) {
 			if ( json.extensionsUsed ) {
 
 
-				if ( json.extensionsUsed.indexOf( EXTENSIONS.KHR_LIGHTS ) >= 0 ) {
+				for ( var i = 0; i < json.extensionsUsed.length; ++ i ) {
 
 
-					extensions[ EXTENSIONS.KHR_LIGHTS ] = new GLTFLightsExtension( json );
+					var extensionName = json.extensionsUsed[ i ];
+					var extensionsRequired = json.extensionsRequired || [];
 
 
-				}
-
-				if ( json.extensionsUsed.indexOf( EXTENSIONS.KHR_MATERIALS_UNLIT ) >= 0 ) {
+					switch ( extensionName ) {
 
 
-					extensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] = new GLTFMaterialsUnlitExtension( json );
+						case EXTENSIONS.KHR_LIGHTS:
+							extensions[ extensionName ] = new GLTFLightsExtension( json );
+							break;
 
 
-				}
+						case EXTENSIONS.KHR_MATERIALS_UNLIT:
+							extensions[ extensionName ] = new GLTFMaterialsUnlitExtension( json );
+							break;
 
 
-				if ( json.extensionsUsed.indexOf( EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ) >= 0 ) {
+						case EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS:
+							extensions[ extensionName ] = new GLTFMaterialsPbrSpecularGlossinessExtension();
+							break;
 
 
-					extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ] = new GLTFMaterialsPbrSpecularGlossinessExtension();
+						case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:
+							extensions[ extensionName ] = new GLTFDracoMeshCompressionExtension( this.dracoLoader );
+							break;
 
 
-				}
+						case EXTENSIONS.MSFT_TEXTURE_DDS:
+							extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] = new GLTFTextureDDSExtension();
+							break;
 
 
-				if ( json.extensionsUsed.indexOf( EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ) >= 0 ) {
+						default:
 
 
-					extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] = new GLTFDracoMeshCompressionExtension( this.dracoLoader );
+							if ( extensionsRequired.indexOf( extensionName ) >= 0 ) {
 
 
-				}
+								console.warn( 'THREE.GLTFLoader: Unknown extension "' + extensionName + '".' );
 
 
-				if ( json.extensionsUsed.indexOf( EXTENSIONS.MSFT_TEXTURE_DDS ) >= 0 ) {
+							}
 
 
-					extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] = new GLTFTextureDDSExtension();
+					}
 
 
 				}
 				}
 
 
@@ -163,16 +172,20 @@ THREE.GLTFLoader = ( function () {
 
 
 			} );
 			} );
 
 
-			parser.parse( function ( scene, scenes, cameras, animations, asset ) {
+			parser.parse( function ( scene, scenes, cameras, animations, json ) {
 
 
 				var glTF = {
 				var glTF = {
 					scene: scene,
 					scene: scene,
 					scenes: scenes,
 					scenes: scenes,
 					cameras: cameras,
 					cameras: cameras,
 					animations: animations,
 					animations: animations,
-					asset: asset
+					asset: json.asset,
+					parser: parser,
+					userData: {}
 				};
 				};
 
 
+				addUnknownExtensionsToUserData( extensions, glTF, json );
+
 				onLoad( glTF );
 				onLoad( glTF );
 
 
 			}, onError );
 			}, onError );
@@ -1150,6 +1163,23 @@ THREE.GLTFLoader = ( function () {
 
 
 	}
 	}
 
 
+	function addUnknownExtensionsToUserData( knownExtensions, object, objectDef ) {
+
+		// Add unknown glTF extensions to an object's userData.
+
+		for ( var name in objectDef.extensions ) {
+
+			if ( knownExtensions[ name ] === undefined ) {
+
+				object.userData.gltfExtensions = object.userData.gltfExtensions || {};
+				object.userData.gltfExtensions[ name ] = objectDef.extensions[ name ];
+
+			}
+
+		}
+
+	}
+
 	/**
 	/**
 	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#morph-targets
 	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#morph-targets
 	 *
 	 *
@@ -1428,10 +1458,9 @@ THREE.GLTFLoader = ( function () {
 			var scenes = dependencies.scenes || [];
 			var scenes = dependencies.scenes || [];
 			var scene = scenes[ json.scene || 0 ];
 			var scene = scenes[ json.scene || 0 ];
 			var animations = dependencies.animations || [];
 			var animations = dependencies.animations || [];
-			var asset = json.asset;
 			var cameras = dependencies.cameras || [];
 			var cameras = dependencies.cameras || [];
 
 
-			onLoad( scene, scenes, cameras, animations, asset );
+			onLoad( scene, scenes, cameras, animations, json );
 
 
 		} ).catch( onError );
 		} ).catch( onError );
 
 
@@ -2110,6 +2139,8 @@ THREE.GLTFLoader = ( function () {
 
 
 			if ( materialDef.extras ) material.userData = materialDef.extras;
 			if ( materialDef.extras ) material.userData = materialDef.extras;
 
 
+			if ( materialDef.extensions ) addUnknownExtensionsToUserData( extensions, material, materialDef );
+
 			return material;
 			return material;
 
 
 		} );
 		} );
@@ -2730,6 +2761,8 @@ THREE.GLTFLoader = ( function () {
 
 
 			if ( nodeDef.extras ) node.userData = nodeDef.extras;
 			if ( nodeDef.extras ) node.userData = nodeDef.extras;
 
 
+			if ( nodeDef.extensions ) addUnknownExtensionsToUserData( extensions, node, nodeDef );
+
 			if ( nodeDef.matrix !== undefined ) {
 			if ( nodeDef.matrix !== undefined ) {
 
 
 				var matrix = new THREE.Matrix4();
 				var matrix = new THREE.Matrix4();
@@ -2862,6 +2895,8 @@ THREE.GLTFLoader = ( function () {
 
 
 				if ( sceneDef.extras ) scene.userData = sceneDef.extras;
 				if ( sceneDef.extras ) scene.userData = sceneDef.extras;
 
 
+				if ( sceneDef.extensions ) addUnknownExtensionsToUserData( extensions, scene, sceneDef );
+
 				var nodeIds = sceneDef.nodes || [];
 				var nodeIds = sceneDef.nodes || [];
 
 
 				for ( var i = 0, il = nodeIds.length; i < il; i ++ ) {
 				for ( var i = 0, il = nodeIds.length; i < il; i ++ ) {