three.js icon indicating copy to clipboard operation
three.js copied to clipboard

GLTFLoader: add getDependency( type, index ) implementation

Open hybridherbst opened this issue 2 years ago • 7 comments

Description

@takahirox requested that the getDependency('light') implementation should be a separate PR, so here it is. This is in preparation for supporting the KHR_animation_pointer glTF extension in three.js.

This PR adds a new way for extensions to implement getDependency( type, index ) for custom types; targets for implementation are right now light and audio.

Related:

  • #24193
  • #24108

hybridherbst avatar Jun 20 '22 07:06 hybridherbst

No conlusion yet but let me share what I'm worried about so far. (It would be better than no response for long.)

I'm thinking whether it is good to let getDependency() in the core glTF loader know the light extension handler. Especially, ._loadLight() of GLTFLightsExtension is expected to be a private method. Ideally the core glTF loader doesn't need to know extensions and their handlers for simplicity.

Perhaps the root issue may be the current plugin system doesn't expect that an extension has dependency with other extensions....

takahirox avatar Jun 21 '22 00:06 takahirox

Yes, with KHR_animation_pointer an extension certainly has dependencies to other extensions.

I think _loadLight being private (having that underscore) doesn't match how the other extensions do that anyways: the extension methods loadAnimation, loadTexture, loadMaterial etc. all are public.

I'm happy to change _loadLight to loadLight so that these are more consistent to each other.

hybridherbst avatar Jun 21 '22 14:06 hybridherbst

I think it might be better to make the glTF plugins expose an optional getDependency(type, index) function which can be used in the default case of the switch statement in getDependency. This would mean any extension could expose its own resources to be used by other extensions or getDependency can be invoked by the user directly.

For example in KHR_audio you could call

getDependency("audioEmitter", 0)

or

getDependency("audioSource", 0)

And the default loader doesn't need to know anything about audioEmitters or audioSources.

robertlong avatar Jul 25 '22 17:07 robertlong

Like this?

// GLTFParser
getDependency( type, index ) {
  const cacheKey = type + ':' + index;
  let dependency = this.cache.get( cacheKey );
  if ( ! dependency ) {
    switch ( type ) {
      ...
      default:
        dependency = this._invokeOne( function ( ext ) {
          return ext !== this && ext.getDependency && ext.getDependency( type, index );
        } );
        if ( ! dependency ) {
          throw new Error( 'Unknown type: ' + type );
        }
        break;
    }
    ...
  }
  ...
}

takahirox avatar Jul 26 '22 21:07 takahirox

Yeah, exactly 👍

robertlong avatar Jul 27 '22 06:07 robertlong

Maybe that sounds good.

Nit: parser.getDependency(type, index) calls .loadXXX(index) that returns the dependency as promise, caches it, and returns it. For consistency, perhaps plugin should have .loadXXX(index) (or .load(type, index)) methods.

// GLTFParser
getDependency( type, index ) {
  const cacheKey = type + ':' + index;
  let dependency = this.cache.get( cacheKey );
  if ( ! dependency ) {
    switch ( type ) {
      ...
      default:
        const functionName = 'load' + type[0].toUpperCase() + type.slice(1); // ugh...
        dependency = this._invokeOne( function ( ext ) {
          return ext[functionName] && ext.[functionName]( index );
          // or return ext.load && ext.load( type, index ); ?
        } );
        if ( ! dependency ) {
          throw new Error( 'Unknown type: ' + type );
        }
        break;
    }
    ...
  }
  ...
}

takahirox avatar Aug 08 '22 21:08 takahirox

I rebased this on dev and implemented the suggestions from here – let me know if that works, thanks @takahirox!

Regarding the .loadXXX approach, not sure if the potential added clarity due to that offsets that weird uppercasing-and-splicing...

hybridherbst avatar Sep 06 '22 21:09 hybridherbst