Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 138 additions & 7 deletions examples/js/loaders/GLTFLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ THREE.GLTFLoader = ( function () {

} );

this.register( function ( parser ) {

return new GLTFMaterialsVariantsExtension( parser );

} );

this.register( function ( parser ) {

return new GLTFLightsExtension( parser );
Expand Down Expand Up @@ -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;

}

}

Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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;

}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: I save variants in scene.userData.variants, too, because they can be used for future glTF exporter support. Otherwise, variants parameter may need to be separately passed to the exporter.


gltf.userData.variants = variants;

gltf.userData.selectVariant = function selectVariant ( variantName ) {
Copy link
Collaborator Author

@takahirox takahirox Nov 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking scene as a parameter instead of using gltf.scenes would be another option.


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
*
Expand Down Expand Up @@ -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 ],
Expand All @@ -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 );

Expand Down
145 changes: 138 additions & 7 deletions examples/jsm/loaders/GLTFLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,12 @@ var GLTFLoader = ( function () {

} );

this.register( function ( parser ) {

return new GLTFMaterialsVariantsExtension( parser );

} );

this.register( function ( parser ) {

return new GLTFLightsExtension( parser );
Expand Down Expand Up @@ -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;

}

}

Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -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 ],
Expand All @@ -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 );

Expand Down
Loading