Skip to content

GLTFLoader: Add support for importing single root files #31112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: dev
Choose a base branch
from
Open
Changes from all commits
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
47 changes: 36 additions & 11 deletions examples/jsm/loaders/GLTFLoader.js
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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'
};

/**
Expand Down Expand Up @@ -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 = [];

Expand All @@ -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 ] );

}

}

Expand Down