Skip to content

Commit 3cc71ef

Browse files
committed
Merge pull request #104184 from aaronfranke/gltf-non-joint-leaf
GLTF: Don't collapse non-joint leaf nodes when importing skeletons
2 parents a19cb97 + dc85b32 commit 3cc71ef

File tree

5 files changed

+274
-24
lines changed

5 files changed

+274
-24
lines changed

modules/gltf/editor/editor_scene_importer_gltf.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ void EditorSceneFormatImporterGLTF::get_import_options(const String &p_path,
8484
String file_extension = p_path.get_extension().to_lower();
8585
// Returns all the options when path is empty because that means it's for the Project Settings.
8686
if (p_path.is_empty() || file_extension == "gltf" || file_extension == "glb") {
87-
r_options->push_back(ResourceImporterScene::ImportOption(PropertyInfo(Variant::INT, "gltf/naming_version", PROPERTY_HINT_ENUM, "Godot 4.1 or 4.0,Godot 4.2 or later"), 1));
87+
r_options->push_back(ResourceImporterScene::ImportOption(PropertyInfo(Variant::INT, "gltf/naming_version", PROPERTY_HINT_ENUM, "Godot 4.0 or 4.1,Godot 4.2 to 4.4,Godot 4.5 or later"), 2));
8888
r_options->push_back(ResourceImporterScene::ImportOption(PropertyInfo(Variant::INT, "gltf/embedded_image_handling", PROPERTY_HINT_ENUM, "Discard All Textures,Extract Textures,Embed as Basis Universal,Embed as Uncompressed", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), GLTFState::HANDLE_BINARY_EXTRACT_TEXTURES));
8989
}
9090
}

modules/gltf/gltf_document.cpp

Lines changed: 233 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5798,7 +5798,16 @@ void GLTFDocument::_assign_node_names(Ref<GLTFState> p_state) {
57985798
}
57995799
}
58005800

5801-
BoneAttachment3D *GLTFDocument::_generate_bone_attachment(Ref<GLTFState> p_state, Skeleton3D *p_skeleton, const GLTFNodeIndex p_node_index, const GLTFNodeIndex p_bone_index) {
5801+
BoneAttachment3D *GLTFDocument::_generate_bone_attachment(Skeleton3D *p_godot_skeleton, const Ref<GLTFNode> &p_bone_node) {
5802+
BoneAttachment3D *bone_attachment = memnew(BoneAttachment3D);
5803+
print_verbose("glTF: Creating bone attachment for: " + p_bone_node->get_name());
5804+
bone_attachment->set_name(p_bone_node->get_name());
5805+
p_godot_skeleton->add_child(bone_attachment, true);
5806+
bone_attachment->set_bone_name(p_bone_node->get_name());
5807+
return bone_attachment;
5808+
}
5809+
5810+
BoneAttachment3D *GLTFDocument::_generate_bone_attachment_compat_4pt4(Ref<GLTFState> p_state, Skeleton3D *p_skeleton, const GLTFNodeIndex p_node_index, const GLTFNodeIndex p_bone_index) {
58025811
Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
58035812
Ref<GLTFNode> bone_node = p_state->nodes[p_bone_index];
58045813
BoneAttachment3D *bone_attachment = memnew(BoneAttachment3D);
@@ -6271,11 +6280,210 @@ void GLTFDocument::_convert_mesh_instance_to_gltf(MeshInstance3D *p_scene_parent
62716280
}
62726281
}
62736282

6283+
void _set_node_tree_owner(Node *p_current_node, Node *&p_scene_root) {
6284+
// Note: p_scene_parent and p_scene_root must either both be null or both be valid.
6285+
if (p_scene_root == nullptr) {
6286+
// If the root node argument is null, this is the root node.
6287+
p_scene_root = p_current_node;
6288+
// If multiple nodes were generated under the root node, ensure they have the owner set.
6289+
if (unlikely(p_current_node->get_child_count() > 0)) {
6290+
Array args;
6291+
args.append(p_scene_root);
6292+
for (int i = 0; i < p_current_node->get_child_count(); i++) {
6293+
Node *child = p_current_node->get_child(i);
6294+
child->propagate_call(StringName("set_owner"), args);
6295+
}
6296+
}
6297+
} else {
6298+
// Add the node we generated and set the owner to the scene root.
6299+
Array args;
6300+
args.append(p_scene_root);
6301+
p_current_node->propagate_call(StringName("set_owner"), args);
6302+
}
6303+
}
6304+
6305+
bool GLTFDocument::_does_skinned_mesh_require_placeholder_node(Ref<GLTFState> p_state, Ref<GLTFNode> p_gltf_node) {
6306+
if (p_gltf_node->skin < 0) {
6307+
return false; // Not a skinned mesh.
6308+
}
6309+
// Check for child nodes that aren't joints/bones.
6310+
for (int i = 0; i < p_gltf_node->children.size(); ++i) {
6311+
Ref<GLTFNode> child = p_state->nodes[p_gltf_node->children[i]];
6312+
if (!child->joint) {
6313+
return true;
6314+
}
6315+
// Edge case: If a child's skeleton is not yet in the tree, then we must add it as a child of this node.
6316+
// While the Skeleton3D node isn't a glTF node, it's still a case where we need a placeholder.
6317+
// This is required to handle this issue: https://github.com/godotengine/godot/issues/67773
6318+
const GLTFSkeletonIndex skel_index = child->skeleton;
6319+
ERR_FAIL_INDEX_V(skel_index, p_state->skeletons.size(), false);
6320+
if (p_state->skeletons[skel_index]->godot_skeleton->get_parent() == nullptr) {
6321+
return true;
6322+
}
6323+
}
6324+
return false;
6325+
}
6326+
62746327
void GLTFDocument::_generate_scene_node(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index, Node *p_scene_parent, Node *p_scene_root) {
62756328
Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
6329+
Node3D *current_node = nullptr;
6330+
// Check if any GLTFDocumentExtension classes want to generate a node for us.
6331+
for (Ref<GLTFDocumentExtension> ext : document_extensions) {
6332+
ERR_CONTINUE(ext.is_null());
6333+
current_node = ext->generate_scene_node(p_state, gltf_node, p_scene_parent);
6334+
if (current_node) {
6335+
break;
6336+
}
6337+
}
6338+
// If none of our GLTFDocumentExtension classes generated us a node, try using built-in glTF types.
6339+
if (!current_node) {
6340+
if (gltf_node->mesh >= 0) {
6341+
current_node = _generate_mesh_instance(p_state, p_node_index);
6342+
// glTF specifies that skinned meshes should ignore their node transforms,
6343+
// only being controlled by the skeleton, so Godot will reparent a skinned
6344+
// mesh to its skeleton. However, we still need to ensure any child nodes
6345+
// keep their place in the tree, so if there are any child nodes, the skinned
6346+
// mesh must not be the base node, so generate an empty spatial base.
6347+
if (_does_skinned_mesh_require_placeholder_node(p_state, gltf_node)) {
6348+
Node3D *placeholder;
6349+
// We need a placeholder, but maybe the Skeleton3D *is* the placeholder?
6350+
const GLTFSkeletonIndex skel_index = gltf_node->skeleton;
6351+
if (skel_index >= 0 && skel_index < p_state->skeletons.size() && p_state->skeletons[skel_index]->godot_skeleton->get_parent() == nullptr) {
6352+
placeholder = p_state->skeletons[skel_index]->godot_skeleton;
6353+
} else {
6354+
placeholder = _generate_spatial(p_state, p_node_index);
6355+
}
6356+
current_node->set_name(gltf_node->get_name());
6357+
placeholder->add_child(current_node, true);
6358+
current_node = placeholder;
6359+
}
6360+
} else if (gltf_node->camera >= 0) {
6361+
current_node = _generate_camera(p_state, p_node_index);
6362+
} else if (gltf_node->light >= 0) {
6363+
current_node = _generate_light(p_state, p_node_index);
6364+
}
6365+
}
6366+
// The only case where current_node is a Skeleton3D is when it is the placeholder for a skinned mesh.
6367+
// In that case, we don't set the name or possibly generate a bone attachment. But usually, we do.
6368+
// It is also possible that user code generates a Skeleton3D node, and this code also works for that case.
6369+
if (likely(!Object::cast_to<Skeleton3D>(current_node))) {
6370+
if (current_node) {
6371+
// Set the name of the Godot node to the name of the glTF node.
6372+
String gltf_node_name = gltf_node->get_name();
6373+
if (!gltf_node_name.is_empty()) {
6374+
current_node->set_name(gltf_node_name);
6375+
}
6376+
}
6377+
// Skeleton stuff: If this node is in a skeleton, we need to attach it to a bone attachment pointing to its bone.
6378+
if (gltf_node->skeleton >= 0) {
6379+
_generate_skeleton_bone_node(p_state, p_node_index, current_node, p_scene_parent, p_scene_root);
6380+
return;
6381+
}
6382+
}
6383+
// Skeleton stuff: If the parent node is in a skeleton, we need to attach this node to a bone attachment pointing to the parent's bone.
6384+
if (Object::cast_to<Skeleton3D>(p_scene_parent)) {
6385+
Skeleton3D *parent_skeleton = Object::cast_to<Skeleton3D>(p_scene_parent);
6386+
_attach_node_to_skeleton(p_state, p_node_index, current_node, parent_skeleton, p_scene_root);
6387+
return;
6388+
}
6389+
// Not a skeleton bone, so definitely some kind of node that goes in the Godot scene tree.
6390+
if (current_node == nullptr) {
6391+
current_node = _generate_spatial(p_state, p_node_index);
6392+
// Set the name of the Godot node to the name of the glTF node.
6393+
String gltf_node_name = gltf_node->get_name();
6394+
if (!gltf_node_name.is_empty()) {
6395+
current_node->set_name(gltf_node_name);
6396+
}
6397+
}
6398+
if (p_scene_parent) {
6399+
p_scene_parent->add_child(current_node, true);
6400+
}
6401+
// Set the owner of the nodes to the scene root.
6402+
// Note: p_scene_parent and p_scene_root must either both be null or both be valid.
6403+
_set_node_tree_owner(current_node, p_scene_root);
6404+
current_node->set_transform(gltf_node->transform);
6405+
current_node->merge_meta_from(*gltf_node);
6406+
p_state->scene_nodes.insert(p_node_index, current_node);
6407+
for (int i = 0; i < gltf_node->children.size(); ++i) {
6408+
_generate_scene_node(p_state, gltf_node->children[i], current_node, p_scene_root);
6409+
}
6410+
}
6411+
6412+
void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index, Node3D *p_current_node, Node *p_scene_parent, Node *p_scene_root) {
6413+
Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
6414+
// Grab the current skeleton, and ensure it's added to the tree.
6415+
Skeleton3D *godot_skeleton = p_state->skeletons[gltf_node->skeleton]->godot_skeleton;
6416+
if (godot_skeleton->get_parent() == nullptr) {
6417+
if (p_scene_root) {
6418+
if (Object::cast_to<Skeleton3D>(p_scene_parent)) {
6419+
Skeleton3D *parent_skeleton = Object::cast_to<Skeleton3D>(p_scene_parent);
6420+
// Explicitly specifying the bone of the parent glTF node is required to
6421+
// handle the edge case where a skeleton is a child of another skeleton.
6422+
_attach_node_to_skeleton(p_state, p_node_index, godot_skeleton, parent_skeleton, p_scene_root, gltf_node->parent);
6423+
} else {
6424+
p_scene_parent->add_child(godot_skeleton, true);
6425+
godot_skeleton->set_owner(p_scene_root);
6426+
}
6427+
} else {
6428+
p_scene_root = godot_skeleton;
6429+
}
6430+
}
6431+
_attach_node_to_skeleton(p_state, p_node_index, p_current_node, godot_skeleton, p_scene_root);
6432+
}
6433+
6434+
void GLTFDocument::_attach_node_to_skeleton(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index, Node3D *p_current_node, Skeleton3D *p_godot_skeleton, Node *p_scene_root, GLTFNodeIndex p_bone_node_index) {
6435+
ERR_FAIL_NULL(p_godot_skeleton->get_parent());
6436+
Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
6437+
if (Object::cast_to<ImporterMeshInstance3D>(p_current_node) && gltf_node->skin >= 0) {
6438+
// Skinned meshes should be attached directly to the skeleton without a BoneAttachment3D.
6439+
ERR_FAIL_COND_MSG(p_current_node->get_child_count() > 0, "Skinned mesh nodes passed to this function should not have children (a placeholder should be inserted by `_generate_scene_node`).");
6440+
p_godot_skeleton->add_child(p_current_node, true);
6441+
} else if (p_current_node || !gltf_node->joint) {
6442+
// If we have a node in need of attaching, we need a BoneAttachment3D.
6443+
// This happens when a node in Blender has Relations -> Parent set to a bone.
6444+
GLTFNodeIndex attachment_node_index = likely(p_bone_node_index == -1) ? (gltf_node->joint ? p_node_index : gltf_node->parent) : p_bone_node_index;
6445+
ERR_FAIL_COND(!p_state->scene_nodes.has(attachment_node_index));
6446+
Node *attachment_godot_node = p_state->scene_nodes[attachment_node_index];
6447+
// If the parent is a Skeleton3D, we need to make a BoneAttachment3D.
6448+
if (Object::cast_to<Skeleton3D>(attachment_godot_node)) {
6449+
Ref<GLTFNode> attachment_gltf_node = p_state->nodes[attachment_node_index];
6450+
BoneAttachment3D *bone_attachment = _generate_bone_attachment(p_godot_skeleton, attachment_gltf_node);
6451+
bone_attachment->set_owner(p_scene_root);
6452+
bone_attachment->merge_meta_from(*p_state->nodes[attachment_node_index]);
6453+
p_state->scene_nodes.insert(attachment_node_index, bone_attachment);
6454+
attachment_godot_node = bone_attachment;
6455+
}
6456+
// By this point, `attachment_godot_node` is either a BoneAttachment3D or part of a BoneAttachment3D subtree.
6457+
// If the node is a plain non-joint, we should generate a Godot node for it.
6458+
if (p_current_node == nullptr) {
6459+
DEV_ASSERT(!gltf_node->joint);
6460+
p_current_node = _generate_spatial(p_state, p_node_index);
6461+
}
6462+
if (!gltf_node->joint) {
6463+
p_current_node->set_transform(gltf_node->transform);
6464+
}
6465+
p_current_node->set_name(gltf_node->get_name());
6466+
attachment_godot_node->add_child(p_current_node, true);
6467+
} else {
6468+
// If this glTF is a plain joint, this glTF node only becomes a Godot bone.
6469+
// We refer to the skeleton itself as this glTF node's corresponding Godot node.
6470+
// This may be overridden later if the joint has a non-joint as a child in need of an attachment.
6471+
p_current_node = p_godot_skeleton;
6472+
}
6473+
_set_node_tree_owner(p_current_node, p_scene_root);
6474+
p_current_node->merge_meta_from(*gltf_node);
6475+
p_state->scene_nodes.insert(p_node_index, p_current_node);
6476+
for (int i = 0; i < gltf_node->children.size(); ++i) {
6477+
_generate_scene_node(p_state, gltf_node->children[i], p_current_node, p_scene_root);
6478+
}
6479+
}
6480+
6481+
// Deprecated code used when naming_version is 0 or 1 (Godot 4.0 to 4.4).
6482+
void GLTFDocument::_generate_scene_node_compat_4pt4(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index, Node *p_scene_parent, Node *p_scene_root) {
6483+
Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
62766484

62776485
if (gltf_node->skeleton >= 0) {
6278-
_generate_skeleton_bone_node(p_state, p_node_index, p_scene_parent, p_scene_root);
6486+
_generate_skeleton_bone_node_compat_4pt4(p_state, p_node_index, p_scene_parent, p_scene_root);
62796487
return;
62806488
}
62816489

@@ -6289,7 +6497,7 @@ void GLTFDocument::_generate_scene_node(Ref<GLTFState> p_state, const GLTFNodeIn
62896497
// skinned meshes must not be placed in a bone attachment.
62906498
if (non_bone_parented_to_skeleton && gltf_node->skin < 0) {
62916499
// Bone Attachment - Parent Case
6292-
BoneAttachment3D *bone_attachment = _generate_bone_attachment(p_state, active_skeleton, p_node_index, gltf_node->parent);
6500+
BoneAttachment3D *bone_attachment = _generate_bone_attachment_compat_4pt4(p_state, active_skeleton, p_node_index, gltf_node->parent);
62936501

62946502
p_scene_parent->add_child(bone_attachment, true);
62956503

@@ -6366,11 +6574,12 @@ void GLTFDocument::_generate_scene_node(Ref<GLTFState> p_state, const GLTFNodeIn
63666574

63676575
p_state->scene_nodes.insert(p_node_index, current_node);
63686576
for (int i = 0; i < gltf_node->children.size(); ++i) {
6369-
_generate_scene_node(p_state, gltf_node->children[i], current_node, p_scene_root);
6577+
_generate_scene_node_compat_4pt4(p_state, gltf_node->children[i], current_node, p_scene_root);
63706578
}
63716579
}
63726580

6373-
void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index, Node *p_scene_parent, Node *p_scene_root) {
6581+
// Deprecated code used when naming_version is 0 or 1 (Godot 4.0 to 4.4).
6582+
void GLTFDocument::_generate_skeleton_bone_node_compat_4pt4(Ref<GLTFState> p_state, const GLTFNodeIndex p_node_index, Node *p_scene_parent, Node *p_scene_root) {
63746583
Ref<GLTFNode> gltf_node = p_state->nodes[p_node_index];
63756584

63766585
Node3D *current_node = nullptr;
@@ -6385,7 +6594,7 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> p_state, const GL
63856594
if (active_skeleton) {
63866595
// Should no longer be possible.
63876596
ERR_PRINT(vformat("glTF: Generating scene detected direct parented Skeletons at node %d", p_node_index));
6388-
BoneAttachment3D *bone_attachment = _generate_bone_attachment(p_state, active_skeleton, p_node_index, gltf_node->parent);
6597+
BoneAttachment3D *bone_attachment = _generate_bone_attachment_compat_4pt4(p_state, active_skeleton, p_node_index, gltf_node->parent);
63896598
p_scene_parent->add_child(bone_attachment, true);
63906599
bone_attachment->set_owner(p_scene_root);
63916600
// There is no gltf_node that represent this, so just directly create a unique name
@@ -6416,7 +6625,7 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> p_state, const GL
64166625
// skinned meshes must not be placed in a bone attachment.
64176626
if (!is_skinned_mesh) {
64186627
// Bone Attachment - Same Node Case
6419-
BoneAttachment3D *bone_attachment = _generate_bone_attachment(p_state, active_skeleton, p_node_index, p_node_index);
6628+
BoneAttachment3D *bone_attachment = _generate_bone_attachment_compat_4pt4(p_state, active_skeleton, p_node_index, p_node_index);
64206629

64216630
p_scene_parent->add_child(bone_attachment, true);
64226631

@@ -6466,7 +6675,7 @@ void GLTFDocument::_generate_skeleton_bone_node(Ref<GLTFState> p_state, const GL
64666675
p_state->scene_nodes.insert(p_node_index, current_node);
64676676

64686677
for (int i = 0; i < gltf_node->children.size(); ++i) {
6469-
_generate_scene_node(p_state, gltf_node->children[i], active_skeleton, p_scene_root);
6678+
_generate_scene_node_compat_4pt4(p_state, gltf_node->children[i], active_skeleton, p_scene_root);
64706679
}
64716680
}
64726681

@@ -7495,6 +7704,7 @@ void GLTFDocument::_process_mesh_instances(Ref<GLTFState> p_state, Node *p_scene
74957704
mi = Object::cast_to<ImporterMeshInstance3D>(si_element->value);
74967705
ERR_CONTINUE_MSG(mi == nullptr, vformat("Unable to cast node %d of type %s to ImporterMeshInstance3D", node_i, si_element->value->get_class_name()));
74977706
}
7707+
ERR_CONTINUE_MSG(mi->get_child_count() > 0, "The glTF importer must generate skinned mesh instances as leaf nodes without any children to allow them to be repositioned in the tree without affecting other nodes.");
74987708

74997709
const GLTFSkeletonIndex skel_i = p_state->skins.write[node->skin]->skeleton;
75007710
Ref<GLTFSkeleton> gltf_skeleton = p_state->skeletons.write[skel_i];
@@ -8425,15 +8635,23 @@ Node *GLTFDocument::_generate_scene_node_tree(Ref<GLTFState> p_state) {
84258635
// Generate the node tree.
84268636
Node *single_root;
84278637
if (p_state->extensions_used.has("GODOT_single_root")) {
8428-
_generate_scene_node(p_state, 0, nullptr, nullptr);
8638+
if (_naming_version < 2) {
8639+
_generate_scene_node_compat_4pt4(p_state, 0, nullptr, nullptr);
8640+
} else {
8641+
_generate_scene_node(p_state, 0, nullptr, nullptr);
8642+
}
84298643
single_root = p_state->scene_nodes[0];
84308644
if (single_root && single_root->get_owner() && single_root->get_owner() != single_root) {
84318645
single_root = single_root->get_owner();
84328646
}
84338647
} else {
84348648
single_root = memnew(Node3D);
84358649
for (int32_t root_i = 0; root_i < p_state->root_nodes.size(); root_i++) {
8436-
_generate_scene_node(p_state, p_state->root_nodes[root_i], single_root, single_root);
8650+
if (_naming_version < 2) {
8651+
_generate_scene_node_compat_4pt4(p_state, p_state->root_nodes[root_i], single_root, single_root);
8652+
} else {
8653+
_generate_scene_node(p_state, p_state->root_nodes[root_i], single_root, single_root);
8654+
}
84378655
}
84388656
}
84398657
// Assign the scene name and single root name to each other
@@ -8525,7 +8743,11 @@ Error GLTFDocument::_parse_gltf_state(Ref<GLTFState> p_state, const String &p_se
85258743
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
85268744

85278745
/* DETERMINE SKELETONS */
8528-
err = SkinTool::_determine_skeletons(p_state->skins, p_state->nodes, p_state->skeletons, p_state->get_import_as_skeleton_bones() ? p_state->root_nodes : Vector<GLTFNodeIndex>());
8746+
if (p_state->get_import_as_skeleton_bones()) {
8747+
err = SkinTool::_determine_skeletons(p_state->skins, p_state->nodes, p_state->skeletons, p_state->root_nodes, true);
8748+
} else {
8749+
err = SkinTool::_determine_skeletons(p_state->skins, p_state->nodes, p_state->skeletons, Vector<GLTFNodeIndex>(), _naming_version < 2);
8750+
}
85298751
ERR_FAIL_COND_V(err != OK, ERR_PARSE_ERROR);
85308752

85318753
/* ASSIGN SCENE NODE NAMES */

0 commit comments

Comments
 (0)