Extensions implementation

I am writing an importer in C#, and I want to support third party extensions.
What is the best way to approach this?

Do I need to carefully insert a slew of delegate ‘hooks’ that a plugin can regiser to, or should i perform standard import if possible, and then call the extension afterwards? Or call it before standard import?
Is there a general rule of when to inject the extensions, and what happens if multiple conflicting extensions are present?

I don’t think there is a standard approach, but the pattern for the glTF loader in Babylon.js may be useful as a reference.

Main loader: Babylon.js/glTFLoader.ts at master · BabylonJS/Babylon.js (github.com)
Extension interface: Babylon.js/glTFLoaderExtension.ts at master · BabylonJS/Babylon.js (github.com)
A bunch of extensions: Babylon.js/loaders/src/glTF/2.0/Extensions at master · BabylonJS/Babylon.js (github.com)

You can read a bit about it from here: Extending the glTF Loader in Babylon.js | by Babylon.js | Medium

I’m not sure there is a general rule. For Babylon.js, each extension has a priority that defines the load order, and sometimes one will win over another.

2 Likes

We took the same approach (simple hooks) in three.js and in glTF-Transform, and this has been working well. Official extensions are designed not to conflict, and if you’re creating custom extensions that would be an important design consideration.

In three.js, there are some hooks for which all extensions are given a chance to run: for example, multiple extensions might append properties to a single material. In other hooks, only the highest-priority extension runs for a particular object: for example, extensions might provide several texture formats (JPEG, Basis Universal, WebP, …) and it is up to the client to decide which is most appropriate and only download that.

I think it would also be possible to perform a “standard” import first and call extensions later, but (1) you’d need to plan standard import carefully for certain extensions, like Draco, which provide all vertex data, and (2) this is potentially less efficient at runtime — you might end up requesting textures or other resources referenced by the extensions in serial, rather than in parallel with the main process.

Here’s a simpler implementation I did recently, in case it’s helpful, also designed to support third-party extension implementations. Some extensions process at the end for now, but there are a few common hooks too:

2 Likes