Enhancing the workflow for artists producing gltf models

@donmccurdy

This post summarizes a bunch of suggestions that would help speed up the workflow for game artists working on creating 3d models.

The first suggestion is the ability to show local files in three-gltf-viewer without having to drag and drop them. This could be done by allowing the viewer app to run in Electron, and having it watch local files for changes using chokidar. I’ve done similar things with my tree-growth generator app and it’s not too difficult. Basically the artist would keep the viewer window open while they were using Blender or Maya, and each time they exported the models to GLTF the model viewer app would update with the new model, without having to explicitly open the file each time.

The reason this is valuable is because models don’t always look exactly the same in Blender as they do when rendered in three.js after being exported to GLTF, and an artist can work faster if the time and effort needed to preview the model can be minimized.

A second suggestion is to accommodate multi-model files. Often times an artist will have a bunch of characters using the same armature and animations. Because of the way GLTF works, you can’t really share resources in another GLTF file (AFAIK), so this requires all the characters to be in the same GLTF file along with their animation data. This makes previewing difficult, since the previewer displays all of the characters simultaneously. What would be helpful is a UI that would allow specific models to be hidden - basically just a checkbox that toggles the ‘visible’ attribute for each model.

Finally, I would like a tree-view widget that allows me to browse the hierarchy of the GLTF file. Again, the reason this is important is that artists often organize their work into collections and folders; and also because Blender’s rules about parenting mean that in many cases the model will be a child of the armature. This hierarchy is often re-arranged during the process of exporting to GLTF, and the resulting structure is sometimes hard for an artist to predict.

Typically a game engine is going to have certain rules for how the model files are organized, and an artist needs to conform to those rules - but that’s difficult for an artist because there’s no tool that allows them to see what the internal structure of the GTLF file looks like. So something like a tree view that would let them santity-check their work would be useful.

2 Likes

I guess these are all suggestions for https://gltf-viewer.donmccurdy.com/?

The first suggestion is the ability to show local files in three-gltf-viewer without having to drag and drop them.

I haven’t tried it personally but this VSCode plugin might help. You can preview models in VSCode using three.js.

I don’t think this is a limitation of glTF, although it does make automatically loading and previewing the separate files harder. But I don’t think there’s any reason why you can’t store animations in a separate file to the model and then use that in your own app.

a checkbox that toggles the ‘visible’ attribute for each model.

This actually would be a nice addition. But might complicate the UI more than @donmccurdy would like. Currently it’s very simple and I guess that is intentional. Same goes for the tree view.

3 Likes

All good ideas! My goals for this particular viewer aren’t that ambitious though, but it’s open source so others can do things like this in forks if they’d like. I was maintaining an Electron build of the viewer for a while, but that ended up being more trouble to maintain than felt worthwhile to me.

I’ve seen people do this by exporting each animation to a glTF/GLB also containing an armature/skeleton (but no skinned mesh). Since each file has the same armature, retargeting the animation at runtime is trivial.

2 Likes

@donmccurdy In your previous message, you said “retargeting the animation at runtime is trivial” - but in fact I have not been able to figure out how to do it. (Sorry for the 8 month delay, I had put this task on the back burner while I work on other parts of the game engine).

The code I have right now looks something like this:

originalArmature.add(skinnedModel);
const newArmatureInstance = SkeletonUtils.clone(this.armature);
originalArmature.remove(skinnedModel);

In other words, I temporarily add the skin as a child of the armature, and then clone it. This gives me a unique instance of the character with both armature and skin.

This works fine if both the skin and the armature are loaded from the same GLTF file. However, if they are loaded from different files, then the skin renders incorrectly, it looks like all the polygons have collapsed in on themselves.

The workflow I had in mind was:

  1. access the gltf.animations (AnimationClip) array from each glTF file
  2. create an AnimationMixer whose root is the character you actually want to animate
  3. play the AnimationClips with that mixer only

This should work on the basis that each KeyframeTrack targets its THREE.Bone only by name, it doesn’t carry a direct reference to the Bone. If the armatures are all the same, with the same skeleton, bone names, and inverse bind matrices, then passing the clips into a mixer with a different root should still work.

I probably overstated in saying “trivial” though, this does require pretty close control of the input models to ensure that they match. It might also require that all of the bones have unique names; the tracks could fall back to UUIDs if not, which would not match across armatures.

1 Like

OK I’ll give that a try. Basically what you are suggesting, if I understand correctly, is not to try and transplant the armature, but only the animation tracks. I think I can make that work.

The way my blender files are set up is that the “humanoid armature”, along with the animation tracks, are in one blender file (named “humanoid-armature.blend”), and then each character skin (along with attachments such as hats) are in a different blender file, where the character has a reference to the armature object using the “link” feature of blender. I have the blender files configured to only export “renderable” objects to GLB - this excludes the camera, sunlight and various scaffolding objects used during editing. The linked armature is marked as renderable, so it gets exported into the GLB along with the skins.

This means that the armatures should be identical, since it is the same data being exported in every case.

@donmccurdy OK that works. Thanks!

2 Likes