GLTF: Don't collapse non-joint leaf nodes when importing skeletons

This commit is contained in:
Aaron Franke 2025-03-16 10:31:17 -07:00
parent 42c7f14422
commit dc85b32a50
No known key found for this signature in database
GPG key ID: 40A1750B977E56BF
5 changed files with 274 additions and 24 deletions

View file

@ -282,11 +282,23 @@ void SkinTool::_recurse_children(
}
}
void SkinTool::_check_if_parent_needs_to_become_joint(const Vector<Ref<GLTFNode>> &p_all_nodes, const Vector<GLTFNodeIndex> &p_skeleton_node_indices, const Ref<GLTFNode> &p_gltf_node, Vector<GLTFNodeIndex> &r_non_joint_indices) {
const GLTFNodeIndex parent_index = p_gltf_node->parent;
if (parent_index >= 0) {
const Ref<GLTFNode> &parent = p_all_nodes[parent_index];
if (!parent->joint && p_skeleton_node_indices.has(parent_index) && !r_non_joint_indices.has(parent_index)) {
_check_if_parent_needs_to_become_joint(p_all_nodes, p_skeleton_node_indices, parent, r_non_joint_indices);
r_non_joint_indices.push_back(parent_index);
}
}
}
Error SkinTool::_determine_skeletons(
Vector<Ref<GLTFSkin>> &skins,
Vector<Ref<GLTFNode>> &nodes,
Vector<Ref<GLTFSkeleton>> &skeletons,
const Vector<GLTFNodeIndex> &p_single_skeleton_roots) {
const Vector<GLTFNodeIndex> &p_single_skeleton_roots,
bool p_turn_non_joint_descendants_into_bones) {
if (!p_single_skeleton_roots.is_empty()) {
Ref<GLTFSkin> skin;
skin.instantiate();
@ -399,14 +411,22 @@ Error SkinTool::_determine_skeletons(
}
}
}
// The nodes placed into `non_joints` will be passed to `_reparent_non_joint_skeleton_subtrees`
// which will add them to the skeleton and set `node->joint` to true.
Vector<SkinNodeIndex> non_joints;
for (int i = 0; i < skeleton_nodes.size(); ++i) {
const SkinNodeIndex node_i = skeleton_nodes[i];
if (nodes[node_i]->joint) {
Ref<GLTFNode> node = nodes[node_i];
if (node->joint) {
if (!p_turn_non_joint_descendants_into_bones) {
// If a joint node has non-joint parents, we need to make them joints as well.
// For example, if A/B/C/D, and A/B and D are joints, then we need to make C a joint as well.
// This is required to handle the "skinD" example in `Animation_Skin_09.gltf` from the glTF-Asset-Generator:
// https://github.com/KhronosGroup/glTF-Asset-Generator/blob/master/Output/Positive/Animation_Skin
_check_if_parent_needs_to_become_joint(nodes, skeleton_nodes, node, non_joints);
}
skeleton->joints.push_back(node_i);
} else {
} else if (p_turn_non_joint_descendants_into_bones) {
non_joints.push_back(node_i);
}
}