From 6b4c81b7cf4cbe974f80555f1caddab754a83c7d Mon Sep 17 00:00:00 2001 From: Takahiro Date: Sun, 29 Nov 2020 16:10:31 -0800 Subject: [PATCH 1/2] GLTFLoader: Implement Materials Variants extension handler as plugin --- examples/js/loaders/GLTFLoader.js | 145 +++++++++++++++++++++-- examples/jsm/loaders/GLTFLoader.js | 145 +++++++++++++++++++++-- examples/webgl_loader_gltf_variants.html | 50 +------- 3 files changed, 282 insertions(+), 58 deletions(-) diff --git a/examples/js/loaders/GLTFLoader.js b/examples/js/loaders/GLTFLoader.js index d29b3c729569ba..66ee7992d75090 100644 --- a/examples/js/loaders/GLTFLoader.js +++ b/examples/js/loaders/GLTFLoader.js @@ -35,6 +35,12 @@ THREE.GLTFLoader = ( function () { } ); + this.register( function ( parser ) { + + return new GLTFMaterialsVariantsExtension( parser ); + + } ); + this.register( function ( parser ) { return new GLTFLightsExtension( parser ); @@ -243,7 +249,11 @@ THREE.GLTFLoader = ( function () { // in addUnknownExtensionsToUserData(). // Remove this workaround if we move all the existing // extension handlers to plugin system - extensions[ plugin.name ] = true; + if ( plugin.addExtensionsToUserData !== true ) { + + extensions[ plugin.name ] = true; + + } } @@ -350,6 +360,7 @@ THREE.GLTFLoader = ( function () { KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness', KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission', KHR_MATERIALS_UNLIT: 'KHR_materials_unlit', + KHR_MATERIALS_VARIANTS: 'KHR_materials_variants', KHR_TEXTURE_BASISU: 'KHR_texture_basisu', KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform', KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization', @@ -733,6 +744,110 @@ THREE.GLTFLoader = ( function () { }; + /** + * Materials variants extension + * + * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_variants + */ + function GLTFMaterialsVariantsExtension( parser ) { + + this.parser = parser; + this.name = EXTENSIONS.KHR_MATERIALS_VARIANTS; + this.addExtensionsToUserData = true; + + } + + GLTFMaterialsVariantsExtension.prototype.afterRoot = function ( gltf ) { + + var parser = this.parser; + var json = parser.json; + var name = this.name; + + if ( ! json.extensions || ! json.extensions[ name ] ) return null; + + var extensionDef = json.extensions[ name ]; + var variantsDef = extensionDef.variants || []; + var variants = []; + + for ( var i = 0, il = variantsDef.length; i < il; i ++ ) { + + variants.push( variantsDef[ i ].name ); + + } + + for ( var i = 0, il = gltf.scenes.length; i < il; i ++ ) { + + gltf.scenes[ i ].userData.variants = variants; + + } + + gltf.userData.variants = variants; + + gltf.userData.selectVariant = function selectVariant ( variantName ) { + + var scenes = gltf.scenes; + var pending = []; + + for ( var i = 0, il = scenes.length; i < il; i ++ ) { + + var scene = scenes[ i ]; + + var variantIndex = variants.indexOf( variantName ); + + if ( variantIndex === - 1 ) continue; + + scene.traverse( function ( object ) { + + if ( ! object.isMesh || ! object.userData.gltfExtensions || + ! object.userData.gltfExtensions[ name ] ) return; + + var meshVariantDef = object.userData.gltfExtensions[ name ]; + var mappings = meshVariantDef.mappings || []; + var materialIndex = - 1; + + for ( var j = 0, jl = mappings.length; j < jl; j ++ ) { + + var mapping = mappings[ j ]; + + if ( mapping.variants.indexOf( variantIndex ) !== - 1 ) { + + materialIndex = mapping.material; + break; + + } + + } + + if ( materialIndex >= 0 ) { + + if ( ! object.userData.originalMaterial ) { + + object.userData.originalMaterial = object.material; + + } + + pending.push( parser.getDependency( 'material', materialIndex ).then( function ( material ) { + + object.material = material; + + } ) ); + + } else if ( object.userData.originalMaterial ) { + + object.material = object.userData.originalMaterial; + + } + + } ); + + } + + return Promise.all( pending ); + + }; + + }; + /** * WebP Texture Extension * @@ -1896,13 +2011,21 @@ THREE.GLTFLoader = ( function () { } ); - Promise.all( [ + Promise.all( this._invokeAll( function ( ext ) { - this.getDependencies( 'scene' ), - this.getDependencies( 'animation' ), - this.getDependencies( 'camera' ), + return ext.beforeRoot && ext.beforeRoot(); - ] ).then( function ( dependencies ) { + } ) ).then( function () { + + return Promise.all( [ + + parser.getDependencies( 'scene' ), + parser.getDependencies( 'animation' ), + parser.getDependencies( 'camera' ), + + ] ); + + } ).then( function ( dependencies ) { var result = { scene: dependencies[ 0 ][ json.scene || 0 ], @@ -1918,7 +2041,15 @@ THREE.GLTFLoader = ( function () { assignExtrasToUserData( result, json ); - onLoad( result ); + Promise.all( parser._invokeAll( function ( ext ) { + + return ext.afterRoot && ext.afterRoot( result ); + + } ) ).then( function () { + + onLoad( result ); + + } ); } ).catch( onError ); diff --git a/examples/jsm/loaders/GLTFLoader.js b/examples/jsm/loaders/GLTFLoader.js index 6eff59a22f17f5..f8c299a266e4a3 100644 --- a/examples/jsm/loaders/GLTFLoader.js +++ b/examples/jsm/loaders/GLTFLoader.js @@ -100,6 +100,12 @@ var GLTFLoader = ( function () { } ); + this.register( function ( parser ) { + + return new GLTFMaterialsVariantsExtension( parser ); + + } ); + this.register( function ( parser ) { return new GLTFLightsExtension( parser ); @@ -308,7 +314,11 @@ var GLTFLoader = ( function () { // in addUnknownExtensionsToUserData(). // Remove this workaround if we move all the existing // extension handlers to plugin system - extensions[ plugin.name ] = true; + if ( plugin.addExtensionsToUserData !== true ) { + + extensions[ plugin.name ] = true; + + } } @@ -415,6 +425,7 @@ var GLTFLoader = ( function () { KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness', KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission', KHR_MATERIALS_UNLIT: 'KHR_materials_unlit', + KHR_MATERIALS_VARIANTS: 'KHR_materials_variants', KHR_TEXTURE_BASISU: 'KHR_texture_basisu', KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform', KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization', @@ -798,6 +809,110 @@ var GLTFLoader = ( function () { }; + /** + * Materials variants extension + * + * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_variants + */ + function GLTFMaterialsVariantsExtension( parser ) { + + this.parser = parser; + this.name = EXTENSIONS.KHR_MATERIALS_VARIANTS; + this.addExtensionsToUserData = true; + + } + + GLTFMaterialsVariantsExtension.prototype.afterRoot = function ( gltf ) { + + var parser = this.parser; + var json = parser.json; + var name = this.name; + + if ( ! json.extensions || ! json.extensions[ name ] ) return null; + + var extensionDef = json.extensions[ name ]; + var variantsDef = extensionDef.variants || []; + var variants = []; + + for ( var i = 0, il = variantsDef.length; i < il; i ++ ) { + + variants.push( variantsDef[ i ].name ); + + } + + for ( var i = 0, il = gltf.scenes.length; i < il; i ++ ) { + + gltf.scenes[ i ].userData.variants = variants; + + } + + gltf.userData.variants = variants; + + gltf.userData.selectVariant = function selectVariant ( variantName ) { + + var scenes = gltf.scenes; + var pending = []; + + for ( var i = 0, il = scenes.length; i < il; i ++ ) { + + var scene = scenes[ i ]; + + var variantIndex = variants.indexOf( variantName ); + + if ( variantIndex === - 1 ) continue; + + scene.traverse( function ( object ) { + + if ( ! object.isMesh || ! object.userData.gltfExtensions || + ! object.userData.gltfExtensions[ name ] ) return; + + var meshVariantDef = object.userData.gltfExtensions[ name ]; + var mappings = meshVariantDef.mappings || []; + var materialIndex = - 1; + + for ( var j = 0, jl = mappings.length; j < jl; j ++ ) { + + var mapping = mappings[ j ]; + + if ( mapping.variants.indexOf( variantIndex ) !== - 1 ) { + + materialIndex = mapping.material; + break; + + } + + } + + if ( materialIndex >= 0 ) { + + if ( ! object.userData.originalMaterial ) { + + object.userData.originalMaterial = object.material; + + } + + pending.push( parser.getDependency( 'material', materialIndex ).then( function ( material ) { + + object.material = material; + + } ) ); + + } else if ( object.userData.originalMaterial ) { + + object.material = object.userData.originalMaterial; + + } + + } ); + + } + + return Promise.all( pending ); + + }; + + }; + /** * WebP Texture Extension * @@ -1961,13 +2076,21 @@ var GLTFLoader = ( function () { } ); - Promise.all( [ + Promise.all( this._invokeAll( function ( ext ) { - this.getDependencies( 'scene' ), - this.getDependencies( 'animation' ), - this.getDependencies( 'camera' ), + return ext.beforeRoot && ext.beforeRoot(); - ] ).then( function ( dependencies ) { + } ) ).then( function () { + + return Promise.all( [ + + parser.getDependencies( 'scene' ), + parser.getDependencies( 'animation' ), + parser.getDependencies( 'camera' ), + + ] ); + + } ).then( function ( dependencies ) { var result = { scene: dependencies[ 0 ][ json.scene || 0 ], @@ -1983,7 +2106,15 @@ var GLTFLoader = ( function () { assignExtrasToUserData( result, json ); - onLoad( result ); + Promise.all( parser._invokeAll( function ( ext ) { + + return ext.afterRoot && ext.afterRoot( result ); + + } ) ).then( function () { + + onLoad( result ); + + } ); } ).catch( onError ); diff --git a/examples/webgl_loader_gltf_variants.html b/examples/webgl_loader_gltf_variants.html index 1fe4c133a7c203..76007e60e84dbf 100644 --- a/examples/webgl_loader_gltf_variants.html +++ b/examples/webgl_loader_gltf_variants.html @@ -69,16 +69,15 @@ // GUI gui = new GUI(); - // Details of the KHR_materials_variants extension used here can be found below - // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_variants - const parser = gltf.parser; - const variantsExtension = gltf.userData.gltfExtensions[ 'KHR_materials_variants' ]; - const variants = variantsExtension.variants.map( ( variant ) => variant.name ); + const variants = gltf.userData.variants; const variantsCtrl = gui.add( state, 'variant', variants ).name( 'Variant' ); - selectVariant( scene, parser, variantsExtension, state.variant ); + variantsCtrl.onChange( async ( value ) => { - variantsCtrl.onChange( ( value ) => selectVariant( scene, parser, variantsExtension, value ) ); + await gltf.userData.selectVariant( value ); + render(); + + } ); render(); @@ -108,43 +107,6 @@ } - function selectVariant( scene, parser, extension, variantName ) { - - const variantIndex = extension.variants.findIndex( ( v ) => v.name.includes( variantName ) ); - - scene.traverse( async ( object ) => { - - if ( ! object.isMesh || ! object.userData.gltfExtensions ) return; - - const meshVariantDef = object.userData.gltfExtensions[ 'KHR_materials_variants' ]; - - if ( ! meshVariantDef ) return; - - if ( ! object.userData.originalMaterial ) { - - object.userData.originalMaterial = object.material; - - } - - const mapping = meshVariantDef.mappings - .find( ( mapping ) => mapping.variants.includes( variantIndex ) ); - - if ( mapping ) { - - object.material = await parser.getDependency( 'material', mapping.material ); - - } else { - - object.material = object.originalMaterial; - - } - - render(); - - } ); - - } - function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; From 550165d17af6b53c6c45d35b0ef85bdbff33af94 Mon Sep 17 00:00:00 2001 From: Takahiro Date: Mon, 30 Nov 2020 23:18:37 -0800 Subject: [PATCH 2/2] GLTFLoader: Export KHR_materials_variants extension handler from the loader --- examples/js/loaders/GLTFLoader.js | 111 ------------------ examples/jsm/loaders/GLTFLoader.js | 111 ------------------ .../gltf_plugins/KHR_materials_variants.js | 104 ++++++++++++++++ examples/webgl_loader_gltf_variants.html | 9 +- 4 files changed, 112 insertions(+), 223 deletions(-) create mode 100644 examples/jsm/loaders/gltf_plugins/KHR_materials_variants.js diff --git a/examples/js/loaders/GLTFLoader.js b/examples/js/loaders/GLTFLoader.js index 66ee7992d75090..86f2c031b7a970 100644 --- a/examples/js/loaders/GLTFLoader.js +++ b/examples/js/loaders/GLTFLoader.js @@ -35,12 +35,6 @@ THREE.GLTFLoader = ( function () { } ); - this.register( function ( parser ) { - - return new GLTFMaterialsVariantsExtension( parser ); - - } ); - this.register( function ( parser ) { return new GLTFLightsExtension( parser ); @@ -360,7 +354,6 @@ THREE.GLTFLoader = ( function () { KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness', KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission', KHR_MATERIALS_UNLIT: 'KHR_materials_unlit', - KHR_MATERIALS_VARIANTS: 'KHR_materials_variants', KHR_TEXTURE_BASISU: 'KHR_texture_basisu', KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform', KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization', @@ -744,110 +737,6 @@ THREE.GLTFLoader = ( function () { }; - /** - * Materials variants extension - * - * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_variants - */ - function GLTFMaterialsVariantsExtension( parser ) { - - this.parser = parser; - this.name = EXTENSIONS.KHR_MATERIALS_VARIANTS; - this.addExtensionsToUserData = true; - - } - - GLTFMaterialsVariantsExtension.prototype.afterRoot = function ( gltf ) { - - var parser = this.parser; - var json = parser.json; - var name = this.name; - - if ( ! json.extensions || ! json.extensions[ name ] ) return null; - - var extensionDef = json.extensions[ name ]; - var variantsDef = extensionDef.variants || []; - var variants = []; - - for ( var i = 0, il = variantsDef.length; i < il; i ++ ) { - - variants.push( variantsDef[ i ].name ); - - } - - for ( var i = 0, il = gltf.scenes.length; i < il; i ++ ) { - - gltf.scenes[ i ].userData.variants = variants; - - } - - gltf.userData.variants = variants; - - gltf.userData.selectVariant = function selectVariant ( variantName ) { - - var scenes = gltf.scenes; - var pending = []; - - for ( var i = 0, il = scenes.length; i < il; i ++ ) { - - var scene = scenes[ i ]; - - var variantIndex = variants.indexOf( variantName ); - - if ( variantIndex === - 1 ) continue; - - scene.traverse( function ( object ) { - - if ( ! object.isMesh || ! object.userData.gltfExtensions || - ! object.userData.gltfExtensions[ name ] ) return; - - var meshVariantDef = object.userData.gltfExtensions[ name ]; - var mappings = meshVariantDef.mappings || []; - var materialIndex = - 1; - - for ( var j = 0, jl = mappings.length; j < jl; j ++ ) { - - var mapping = mappings[ j ]; - - if ( mapping.variants.indexOf( variantIndex ) !== - 1 ) { - - materialIndex = mapping.material; - break; - - } - - } - - if ( materialIndex >= 0 ) { - - if ( ! object.userData.originalMaterial ) { - - object.userData.originalMaterial = object.material; - - } - - pending.push( parser.getDependency( 'material', materialIndex ).then( function ( material ) { - - object.material = material; - - } ) ); - - } else if ( object.userData.originalMaterial ) { - - object.material = object.userData.originalMaterial; - - } - - } ); - - } - - return Promise.all( pending ); - - }; - - }; - /** * WebP Texture Extension * diff --git a/examples/jsm/loaders/GLTFLoader.js b/examples/jsm/loaders/GLTFLoader.js index f8c299a266e4a3..e44a74676c479a 100644 --- a/examples/jsm/loaders/GLTFLoader.js +++ b/examples/jsm/loaders/GLTFLoader.js @@ -100,12 +100,6 @@ var GLTFLoader = ( function () { } ); - this.register( function ( parser ) { - - return new GLTFMaterialsVariantsExtension( parser ); - - } ); - this.register( function ( parser ) { return new GLTFLightsExtension( parser ); @@ -425,7 +419,6 @@ var GLTFLoader = ( function () { KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness', KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission', KHR_MATERIALS_UNLIT: 'KHR_materials_unlit', - KHR_MATERIALS_VARIANTS: 'KHR_materials_variants', KHR_TEXTURE_BASISU: 'KHR_texture_basisu', KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform', KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization', @@ -809,110 +802,6 @@ var GLTFLoader = ( function () { }; - /** - * Materials variants extension - * - * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_variants - */ - function GLTFMaterialsVariantsExtension( parser ) { - - this.parser = parser; - this.name = EXTENSIONS.KHR_MATERIALS_VARIANTS; - this.addExtensionsToUserData = true; - - } - - GLTFMaterialsVariantsExtension.prototype.afterRoot = function ( gltf ) { - - var parser = this.parser; - var json = parser.json; - var name = this.name; - - if ( ! json.extensions || ! json.extensions[ name ] ) return null; - - var extensionDef = json.extensions[ name ]; - var variantsDef = extensionDef.variants || []; - var variants = []; - - for ( var i = 0, il = variantsDef.length; i < il; i ++ ) { - - variants.push( variantsDef[ i ].name ); - - } - - for ( var i = 0, il = gltf.scenes.length; i < il; i ++ ) { - - gltf.scenes[ i ].userData.variants = variants; - - } - - gltf.userData.variants = variants; - - gltf.userData.selectVariant = function selectVariant ( variantName ) { - - var scenes = gltf.scenes; - var pending = []; - - for ( var i = 0, il = scenes.length; i < il; i ++ ) { - - var scene = scenes[ i ]; - - var variantIndex = variants.indexOf( variantName ); - - if ( variantIndex === - 1 ) continue; - - scene.traverse( function ( object ) { - - if ( ! object.isMesh || ! object.userData.gltfExtensions || - ! object.userData.gltfExtensions[ name ] ) return; - - var meshVariantDef = object.userData.gltfExtensions[ name ]; - var mappings = meshVariantDef.mappings || []; - var materialIndex = - 1; - - for ( var j = 0, jl = mappings.length; j < jl; j ++ ) { - - var mapping = mappings[ j ]; - - if ( mapping.variants.indexOf( variantIndex ) !== - 1 ) { - - materialIndex = mapping.material; - break; - - } - - } - - if ( materialIndex >= 0 ) { - - if ( ! object.userData.originalMaterial ) { - - object.userData.originalMaterial = object.material; - - } - - pending.push( parser.getDependency( 'material', materialIndex ).then( function ( material ) { - - object.material = material; - - } ) ); - - } else if ( object.userData.originalMaterial ) { - - object.material = object.userData.originalMaterial; - - } - - } ); - - } - - return Promise.all( pending ); - - }; - - }; - /** * WebP Texture Extension * diff --git a/examples/jsm/loaders/gltf_plugins/KHR_materials_variants.js b/examples/jsm/loaders/gltf_plugins/KHR_materials_variants.js new file mode 100644 index 00000000000000..81ec1b5eee5891 --- /dev/null +++ b/examples/jsm/loaders/gltf_plugins/KHR_materials_variants.js @@ -0,0 +1,104 @@ +/** + * Materials variants extension + * + * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_variants + */ +export default function GLTFMaterialsVariantsExtension( parser ) { + + this.parser = parser; + this.name = 'KHR_materials_variants'; + this.addExtensionsToUserData = true; + +} + +GLTFMaterialsVariantsExtension.prototype.afterRoot = function ( gltf ) { + + var parser = this.parser; + var json = parser.json; + var name = this.name; + + if ( ! json.extensions || ! json.extensions[ name ] ) return null; + + var extensionDef = json.extensions[ name ]; + var variantsDef = extensionDef.variants || []; + var variants = []; + + for ( var i = 0, il = variantsDef.length; i < il; i ++ ) { + + variants.push( variantsDef[ i ].name ); + + } + + for ( var i = 0, il = gltf.scenes.length; i < il; i ++ ) { + + gltf.scenes[ i ].userData.variants = variants; + + } + + gltf.userData.variants = variants; + + gltf.userData.selectVariant = function selectVariant ( variantName ) { + + var scenes = gltf.scenes; + var pending = []; + + for ( var i = 0, il = scenes.length; i < il; i ++ ) { + + var scene = scenes[ i ]; + + var variantIndex = variants.indexOf( variantName ); + + if ( variantIndex === - 1 ) continue; + + scene.traverse( function ( object ) { + + if ( ! object.isMesh || ! object.userData.gltfExtensions || + ! object.userData.gltfExtensions[ name ] ) return; + + var meshVariantDef = object.userData.gltfExtensions[ name ]; + var mappings = meshVariantDef.mappings || []; + var materialIndex = - 1; + + for ( var j = 0, jl = mappings.length; j < jl; j ++ ) { + + var mapping = mappings[ j ]; + + if ( mapping.variants.indexOf( variantIndex ) !== - 1 ) { + + materialIndex = mapping.material; + break; + + } + + } + + if ( materialIndex >= 0 ) { + + if ( ! object.userData.originalMaterial ) { + + object.userData.originalMaterial = object.material; + + } + + pending.push( parser.getDependency( 'material', materialIndex ).then( function ( material ) { + + object.material = material; + parser.assignFinalMaterial( object ); + + } ) ); + + } else if ( object.userData.originalMaterial ) { + + object.material = object.userData.originalMaterial; + + } + + } ); + + } + + return Promise.all( pending ); + + }; + +}; diff --git a/examples/webgl_loader_gltf_variants.html b/examples/webgl_loader_gltf_variants.html index 76007e60e84dbf..2ba971f912ac5a 100644 --- a/examples/webgl_loader_gltf_variants.html +++ b/examples/webgl_loader_gltf_variants.html @@ -24,6 +24,8 @@ import { GLTFLoader } from './jsm/loaders/GLTFLoader.js'; import { RGBELoader } from './jsm/loaders/RGBELoader.js'; + import GLTFMaterialsVariantsExtension from './jsm/loaders/gltf_plugins/KHR_materials_variants.js'; + let camera, scene, renderer; let gui; @@ -59,7 +61,12 @@ // model - const loader = new GLTFLoader().setPath( 'models/gltf/MaterialsVariantsShoe/glTF/' ); + const loader = new GLTFLoader().register( function ( parser ) { + + return new GLTFMaterialsVariantsExtension( parser ); + + } ).setPath( 'models/gltf/MaterialsVariantsShoe/glTF/' ); + loader.load( 'MaterialsVariantsShoe.gltf', function ( gltf ) { gltf.scene.scale.set( 10.0, 10.0, 10.0 );