diff --git a/examples/jsm/loaders/GLTFLoader.js b/examples/jsm/loaders/GLTFLoader.js index e8593bd4c60d56..eb72301b40e981 100644 --- a/examples/jsm/loaders/GLTFLoader.js +++ b/examples/jsm/loaders/GLTFLoader.js @@ -97,6 +97,7 @@ import { toTrianglesDrawMode } from '../utils/BufferGeometryUtils.js'; * - EXT_texture_webp * - EXT_meshopt_compression * - EXT_mesh_gpu_instancing + * - GODOT_single_root * * The following glTF 2.0 extension is supported by an external user plugin: * - [KHR_materials_variants]{@link https://github.com/takahirox/three-gltf-extensions} @@ -405,7 +406,7 @@ class GLTFLoader extends Loader { } /** - * Parses the given FBX data and returns the resulting group. + * Parses the given glTF data and returns the generated data to `onLoad`. * * @param {string|ArrayBuffer} data - The raw glTF data. * @param {string} path - The URL base path. @@ -619,7 +620,8 @@ const EXTENSIONS = { EXT_TEXTURE_WEBP: 'EXT_texture_webp', EXT_TEXTURE_AVIF: 'EXT_texture_avif', EXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression', - EXT_MESH_GPU_INSTANCING: 'EXT_mesh_gpu_instancing' + EXT_MESH_GPU_INSTANCING: 'EXT_mesh_gpu_instancing', + GODOT_SINGLE_ROOT: 'GODOT_single_root' }; /** @@ -4479,18 +4481,33 @@ class GLTFParser { const extensions = this.extensions; const sceneDef = this.json.scenes[ sceneIndex ]; + const nodeIds = sceneDef.nodes || []; const parser = this; + const extensionsUsed = this.json.extensionsUsed; + const isGodotSingleRoot = Array.isArray( extensionsUsed ) ? extensionsUsed.includes( EXTENSIONS.GODOT_SINGLE_ROOT ) : false; - // Loader returns Group, not Scene. - // See: https://github.com/mrdoob/three.js/issues/18342#issuecomment-578981172 - const scene = new Group(); - if ( sceneDef.name ) scene.name = parser.createUniqueName( sceneDef.name ); + let scene; - assignExtrasToUserData( scene, sceneDef ); + if ( isGodotSingleRoot ) { - if ( sceneDef.extensions ) addUnknownExtensionsToUserData( extensions, scene, sceneDef ); + if ( nodeIds.length !== 1 ) { - const nodeIds = sceneDef.nodes || []; + throw new Error( 'THREE.GLTFLoader: glTF files using the GODOT_single_root extension must have exactly one scene root node. File is invalid.' ); + + } + + } else { + + // Loader returns Group, not Scene. + // See: https://github.com/mrdoob/three.js/issues/18342#issuecomment-578981172 + scene = new Group(); + if ( sceneDef.name ) scene.name = parser.createUniqueName( sceneDef.name ); + + assignExtrasToUserData( scene, sceneDef ); + + if ( sceneDef.extensions ) addUnknownExtensionsToUserData( extensions, scene, sceneDef ); + + } const pending = []; @@ -4502,9 +4519,17 @@ class GLTFParser { return Promise.all( pending ).then( function ( nodes ) { - for ( let i = 0, il = nodes.length; i < il; i ++ ) { + if ( isGodotSingleRoot ) { - scene.add( nodes[ i ] ); + scene = nodes[ 0 ]; + + } else { + + for ( let i = 0, il = nodes.length; i < il; i ++ ) { + + scene.add( nodes[ i ] ); + + } }