KhronosGroup / glTF-Blender-IO

Blender glTF 2.0 importer and exporter
https://docs.blender.org/manual/en/latest/addons/import_export/scene_gltf2.html
Apache License 2.0
1.5k stars 319 forks source link

Incorrect armature structure on import #1893

Closed NotNite closed 1 year ago

NotNite commented 1 year ago

Heya,

Me and a few friends have been working on a tool to export models from the game FINAL FANTASY XIV, written in C# using SharpGLTF. I came across an issue that I originally thought was a SharpGLTF bug, but after trying with several other glTF importers online and the Godot Engine, I think(?) this is a bug in Blender importing glTF files. I'm using Blender 3.5.0, addon 3.5.30, Windows 10 22H2 (19045).

For reference, we're trying to build a custom exporter for glTF compared to the game community's current FBX exporter.


SharpGLTF's API for adding a skinned mesh is AddSkinnedMesh(MESHBUILDER mesh, Matrix4x4 meshWorldMatrix, params NodeBuilder[] joints) - our old approach (on the model-export branch of our repository) was to pass every single bone into the joints parameter.

This resulted in 100+ vertex groups on every single mesh when only a few were being used (left: reference model, right: our model):

I refactored the code (on the model-export-but-broken branch) to only pass the bones that get used to AddSkinnedMesh (while still keeping the entire skeleton node inside of the scene). However, that turned this (model-export):

into this (model-export-but-broken):

It seems that Blender is now unable to detect that n_root is the actual root of the skeleton. Furthermore, some bones (j_mune_l, for example) aren't even in the skeleton at all - just loose objects.

Trying with the Godot Engine model import correctly detects the n_root bone as the root, and you can notice j_mune_l is where it is supposed to be:


Some resources:

julienduroure commented 1 year ago

Hello, During import:

But in your case, some descendants of joints, that are not in joints list, and are not meshed, are created as empties. I am not sure we can be sure that these nodes should be created as bone or as empties.

One solution should be to mask as bones any descendants of bones until finding a node that is not "empty" (mesh or lamp, camera, etc...). Not sure this is what we want. The best way to be sure to create these nodes as bones is to add them to the joint list (this is the aims of this list). What is the purpose to be sure they are bones? (as they don't have any weights assigned, as they are not in join list) ?

@scurest any thoughts?

(In 3.5, I am not able to reproduce your issue about n_root, that is created as bone)

image

NotNite commented 1 year ago

What is the purpose to be sure they are bones? (as they don't have any weights assigned, as they are not in join list) ?

As this is a tool primarily intended for modders of the game, we plan to also get importing glTF->proprietary model format to work, and it would be much harder to build with an incorrect armature.

Of course, we don't need to remove the unused items - it's just a quality of life feature to make navigating that menu easier. If this sounds too out of scope, let me know, and I can close this.

julienduroure commented 1 year ago

Hello,

Let's close this ticket, as we currently set as bone cases where we are sure that nodes are bones. Any other case are cases where we can't be sure if we need bone or empty, depending on user workflow.