Skip to content

GLTFLoader: record association between glTF elements and Three.js objects #19257

@cdata

Description

@cdata

Note: I don't want to bury the lede for this request, so I moved a brief summary to the top of the issue. Please refer to the second and third headings for a more detailed background and rationale!

Proposal

When loading models with GLTFLoader, it would be nice if we could retain associations between glTF scene graph elements and the Three.js objects that correspond to them. I briefly discussed this problem with @donmccurdy and he suggested that one of the following approaches might be acceptable:

  1. Decorate Three.js objects via userData e.g., material.userData.gltfMeta.index = 3
  2. Expose a lookup table somewhere e.g., parser.getDefinition( material: THREE.Material ): GLTF.Material

What do others think about this problem? Would you be willing to consider a change that makes either of the suggested enhancements?

Background

Three.js' GLTFLoader currently produces an artifact that contains a Three.js scene graph as well as a GLTFParser instance that holds the original, deserialized glTF.

The GLTFParser holds associations between the elements in the original glTF and the Three.js scene graph. These associations are expressed both by GLTFParser.prototype.getDependencies and the cache object on the GLTFParser instance.

In some cases, the relationship between the original glTF element and the associated Three.js objects is obscured and cannot be trivially re-established. For example, materials associated with a skinned mesh are cloned, and the resulting clones are cached against a key that cannot be reconstructed easily:

cachedMaterial = material.clone();
if ( useSkinning ) cachedMaterial.skinning = true;
if ( useVertexTangents ) cachedMaterial.vertexTangents = true;
if ( useVertexColors ) cachedMaterial.vertexColors = true;
if ( useFlatShading ) cachedMaterial.flatShading = true;
if ( useMorphTargets ) cachedMaterial.morphTargets = true;
if ( useMorphNormals ) cachedMaterial.morphNormals = true;
this.cache.add( cacheKey, cachedMaterial );

Description of the problem

Consider a model editor that allows a user to:

  1. Load a glTF with any shape
  2. Interactively change the value of any field of any element of the glTF
  3. See the result of the change rendered in real time
  4. Export a new glTF

In an ideal world, the editor should faithfully re-export the model with its original hierarchy and shape. The only meaningful change in the exported file should be the one made interactively by the user.

In the pursuit of this goal, it is very useful (and probably required) that an association between the source glTF scene graph and the Three.js scene graph be made, so that for any change we make to a glTF element, we can reflect that change in the rendered Three.js scene in real-time without completely re-loading the glTF.

Some of the information required to correctly correlate the glTF scene graph with the Three.js scene graph is lost or obscured, and this makes the above described editor scenario very difficult (perhaps impossible) to achieve.

Three.js version
  • Dev
  • r115
  • ...
Browser
  • All of them
  • Chrome
  • Firefox
  • Internet Explorer
OS
  • All of them
  • Windows
  • macOS
  • Linux
  • Android
  • iOS
Hardware Requirements (graphics card, VR Device, ...)

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions