godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
86.86k stars 19.45k forks source link

Blender asset import creates a new bone for every object parented to same bone #75917

Open smix8 opened 1 year ago

smix8 commented 1 year ago

Godot version

c3ed7af

System information

Windows 10

Issue description

When importing a Blender 3D asset the Godot asset importer creates a new bone and a new BoneAttachment3D for each object that was parented to a skeleton bone, e.g. each mesh item. Even if this behavior is wanted there is imo a bug when 100 objects are parented all to the very same bone in Blender the Godot importer adds +100 additional bones instead of just one extra bone.

This can result in a very excessive amount of extra bones on complex skeletons with many attachments for e.g. character customization. As mentioned in related https://github.com/godotengine/godot/issues/75915 having so many extra bones is slow to work with and consumes performance for mostly nothing.

Godot 3 did not add extra bones for each bone attachment but this was apparently changed to solve other bugs with bone index shuffling like https://github.com/godotengine/godot/issues/64512 and https://github.com/godotengine/godot/issues/61641.

Steps to reproduce

Minimal reproduction project

BlenderTestFile.zip

TokageItLab commented 2 months ago

Was this behavior added at some point in the 4.0 alpha? This may be tough since it is old, but can you identify the commit or PR that added this in Blame or Bisect?

smix8 commented 2 months ago

Consider there are duplicated issues for this from 4.0.2 and my issues is even older it was somewhere in Godot 4.0 alpha. Likely from the begin with the GLTF importer rework as Godot 3 does not have the problem.

lyuma commented 2 months ago

It would be caused by #72158 - this was where I changed skeletons to recursively contain all gltf nodes (which includes mesh nodes).

This fix was made in response to issues such as #67773 in which meshes were also bones. glTF doesn't distinguish nodes from bones, so it is difficult to adapt data to use an armature/skeleton model.

TokageItLab commented 2 months ago

In other words, is the problem dependent on Blender's scene tree structure and should be fixed by the glTF exporter? I remember glTF breaking depending on the parent-child relationship between the mesh and armature when I export it from blender.

lyuma commented 2 months ago

In a strictly technical sense, there is no problem. The glTF spec doesn't specify how to map things to/from nodes to armatures.

Blender does a pretty good job of including various hints in the exported gltf. So there is no way to improve Blender's gltf exporter other then maybe some extension that says like it's ok to listen to the hints precisely

Godot ignores a lot of those hints because they can be unreliable from other DCC. In that PR, I changed Godot to prefer correctness and stability across imports at the expense of a few extra bones. I believe the current approach is more correct.

I respect that some people such as smix want fewer bones as an import option, so this is something I can work on. There were some problems with the code we inherited from Godot 3, especially in the instance of nested armatures. I am worried about reintroducing the Godot 3 code exactly so it would be better to properly design this feature rather than just do what godot 3 did

lyuma commented 2 months ago

In summary, I am proposing two separate things here.

  1. An extension for blender or an import option which is true in godot that says "trust the unreliable gltf hints exactly". This option or extension would disable all of the godot skeleton detection code and assume the gltf skeletons and skins are divided precisely into armatures in the way blender does.
  2. An option for some sort of armature detection that works more similarly to godot 3, but ideally simplify the logic since the code we inherited for this purpose is highly complex, slow and easy to break compatibility.
TokageItLab commented 2 months ago
  1. An extension for blender or an import option which is true in godot that says "trust the unreliable gltf hints exactly". This option or extension would disable all of the godot skeleton detection code and assume the gltf skeletons and skins are divided precisely into armatures in the way blender does.

Method 1 sounds more like the right way to go than 2.

KnightNine commented 2 months ago

I want to note that the extra "new bones" created for each bone-child mesh contain the offsets of the mesh from the skeleton as the BoneAttachment3D node copies the transforms of the bone it is assigned to.

These if these new bones were to be removed either BoneAttachment3D should have support for "transform offsets" or the offsets should be applied to the mesh itself.