Skip to content

Commit

Permalink
Keep global rest of unmapped bones if no mapped bone descendants
Browse files Browse the repository at this point in the history
  • Loading branch information
ydeltastar committed May 5, 2024
1 parent 7ebc866 commit d6d9a4c
Showing 1 changed file with 52 additions and 5 deletions.
57 changes: 52 additions & 5 deletions editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ void PostImportPluginSkeletonRestFixer::get_internal_import_options(InternalImpo
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/apply_node_transforms"), true));
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/normalize_position_tracks"), true));
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/overwrite_axis"), true));
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/keep_unmapped_axis"), false));
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/reset_all_bone_poses_after_import"), true));
r_options->push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "retarget/rest_fixer/fix_silhouette/enable"), false));
// TODO: PostImportPlugin need to be implemented such as validate_option(PropertyInfo &property, const Dictionary &p_options).
Expand Down Expand Up @@ -447,6 +448,54 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
old_skeleton_global_rest.push_back(src_skeleton->get_bone_global_rest(i));
}

bool keep_unmapped_axis = bool(p_options["retarget/rest_fixer/keep_unmapped_axis"]);

// Scan hierarchy and populate a whitelist of unmapped bones without mapped descendants.
Vector<int> keep_bone_rest;
if (keep_unmapped_axis) {
// Scan descendants for mapped bones.
std::function<bool(int)> has_mapped_desc = [&](int parent_bone) {
Vector<int> bones_to_process = src_skeleton->get_bone_children(parent_bone);
while (bones_to_process.size() > 0) {
int src_idx = bones_to_process[0];
bones_to_process.erase(src_idx);
Vector<int> src_children = src_skeleton->get_bone_children(src_idx);
for (int i = 0; i < src_children.size(); i++) {
bones_to_process.push_back(src_children[i]);
}

StringName src_bone_name = is_renamed ? StringName(src_skeleton->get_bone_name(src_idx)) : bone_map->find_profile_bone_name(src_skeleton->get_bone_name(src_idx));
if (src_bone_name != StringName()) {
if (profile->has_bone(src_bone_name)) {
return true;
}
}
}

return false;
};

// Populate list
Vector<int> bones_to_process = src_skeleton->get_parentless_bones();
while (bones_to_process.size() > 0) {
int src_idx = bones_to_process[0];
bones_to_process.erase(src_idx);
Vector<int> src_children = src_skeleton->get_bone_children(src_idx);
for (int i = 0; i < src_children.size(); i++) {
bones_to_process.push_back(src_children[i]);
}

StringName src_bone_name = is_renamed ? StringName(src_skeleton->get_bone_name(src_idx)) : bone_map->find_profile_bone_name(src_skeleton->get_bone_name(src_idx));
if (src_bone_name != StringName()) {
if (!profile->has_bone(src_bone_name)) {
if (!has_mapped_desc(src_idx)) {
keep_bone_rest.push_back(src_idx); // No mapped descendants. Add to whitelist.
}
}
}
}
}

Vector<Basis> diffs;
diffs.resize(src_skeleton->get_bone_count());
Basis *diffs_w = diffs.ptrw();
Expand All @@ -472,13 +521,11 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
int prof_idx = profile->find_bone(src_bone_name);
if (prof_idx >= 0) {
tgt_rot = src_pg.inverse() * prof_skeleton->get_bone_global_rest(prof_idx).basis; // Mapped bone uses reference pose.
}
/*
// If there is rest-relative animation, this logic may be work fine, but currently not so...
} else {
// tgt_rot = src_pg.inverse() * old_skeleton_global_rest[src_idx].basis; // Non-Mapped bone keeps global rest.
if (keep_unmapped_axis && keep_bone_rest.has(src_idx)) {
tgt_rot = src_pg.inverse() * old_skeleton_global_rest[src_idx].basis; // Non-Mapped bone without mapped children keeps global rest.
}
}
*/
}

if (src_skeleton->get_bone_parent(src_idx) >= 0) {
Expand Down

0 comments on commit d6d9a4c

Please sign in to comment.