glTF-Transform
glTF-Transform copied to clipboard
Support transferring properties to another Document
The graph datastructure under glTF Transform prevents sharing property resources (materials, textures, animations...) between multiple Document instances. That's important for reference tracking, but does make certain cases harder than they need to be. For example, moving a material from one glTF file into another.
We could consider creating a simple API to handle this case. Possible APIs...
const material = document.transfer(externalMaterial); // single
const materials = document.transfer(externalMaterials); // multiple
const material = externalMaterial.cloneExternal(document);
I think I'm leaning toward dstProperties = document.transfer(srcProperties)
. Accepting an array would be important on the assumption that the transferred properties might share references to underlying resources like textures, and we don't want to create duplicates of those.
For my own understanding, it would be helpful to see the API examples in terms of doc1
and doc2
to show how the transfer completes. Does transfer
go into or out of the document? I also noticed a detach()
method in your docs, but I'm unclear what it's for - could it be related to these flows?
Sure, in terms of src
and dst
documents —
src.getRoot().listTextures(); // → [texture1, texture2, texture3, ...]
dst.getRoot().listTextures(); // → []
dst.transfer(src.getRoot().listTextures());
src.getRoot().listTextures(); // → []
dst.getRoot().listTextures(); // → [texture1, texture2, texture3, ...]
I'm thinking it's fine for these resource to be removed from the src
document, but I'm not married to that idea. The detach()
method is probably part of this solution, but not all of it — detaching removes all inbound references to a resource from other resources in the document, but doesn't remove the resource's connection to the document itself.
Interesting - the problem I see here is with a material that references a texture. I'd like to transfer that material and not have it broken, so I need its texture transferred too, automatically ideally. However, if another material in the src document also references that texture, then removing it seems problematic. Likewise with transferring a node and pulling all of the things it references, recursively.
What about this?
dst.cloneSubTree(src.getRoot().listNodes()[2]);
Yes, for any of these APIs I am assuming the process is recursive, and e.g. textures will be kept with the material. That's part of the motivation for an array parameter. With a single-argument API, I don't think I'd be able to avoid creating duplicates of any shared textures:
// duplicate textures!
dst.transfer(material1);
dst.transfer(material2);
// ok
dst.transfer([material1, material2]);
Ah, that makes sense, thanks. And I suppose if the dangling references in the src
are just nulled out, then everything will still be in a good state.
Another suggestion to this API: cloneExternal
method on all PropertyTypes which takes buffer
as an optional argument. If that returns a new accessor, we can attach it whatever document we want (which is associated with the passed buffer
).
I'm not sure I understand what you would like to happen with the buffer
argument – would it be the same thing as finding the Document associated with that Buffer, and passing that Document in instead?
I was talking about the argument passed to Accessor.setBuffer
.
would it be the same thing as finding the Document associated with that Buffer, and passing that Document in instead
I think this works too. I was not aware this can be done.
Also, just curious, what if we detach the property and all it's child properties and attach the parent property to the new document? That works too right?
None of this is supported now, but that's the idea for the proposal here yes. 👍🏻
Proposed solution:
- https://github.com/donmccurdy/glTF-Transform/pull/1375