From 6a6bd2307c66ed70e49fc0a2c83f41b55026b220 Mon Sep 17 00:00:00 2001 From: Lyuma Date: Sun, 25 Feb 2024 02:26:54 -0800 Subject: [PATCH] Add rest fixer toggle to disable bone pose reset Adds a "Reset All Bone Poses After Import" option to the Skeleton3D Rest Fixer settings. Default value of true resets the bone poses to rest (usually a t-pose), matching previous behavior. If disabled, keeps the bones posed as they would have been before silhouette adjustment. --- ...post_import_plugin_skeleton_rest_fixer.cpp | 44 ++++++++++++++++--- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp index 53bf24fb7ed..d2318c0c697 100644 --- a/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp +++ b/editor/import/3d/post_import_plugin_skeleton_rest_fixer.cpp @@ -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/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). // get_internal_option_visibility() is not sufficient because it can only retrieve options implemented in the core and can only read option values. @@ -113,6 +114,10 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory Vector bones_to_process = src_skeleton->get_parentless_bones(); for (int i = 0; i < bones_to_process.size(); i++) { src_skeleton->set_bone_rest(bones_to_process[i], global_transform.orthonormalized() * src_skeleton->get_bone_rest(bones_to_process[i])); + + src_skeleton->set_bone_pose_position(bones_to_process[i], global_transform.orthonormalized().xform(src_skeleton->get_bone_pose_position(bones_to_process[i]))); + src_skeleton->set_bone_pose_rotation(bones_to_process[i], global_transform.basis.get_rotation_quaternion() * src_skeleton->get_bone_pose_rotation(bones_to_process[i])); + src_skeleton->set_bone_pose_scale(bones_to_process[i], (global_transform.orthonormalized().basis * Basis().scaled(src_skeleton->get_bone_pose_scale((bones_to_process[i])))).get_scale()); } while (bones_to_process.size() > 0) { @@ -123,6 +128,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory bones_to_process.push_back(src_children[i]); } src_skeleton->set_bone_rest(src_idx, Transform3D(src_skeleton->get_bone_rest(src_idx).basis, src_skeleton->get_bone_rest(src_idx).origin * scl)); + src_skeleton->set_bone_pose_position(src_idx, src_skeleton->get_bone_pose_position(src_idx) * scl); } // Fix animation. @@ -603,6 +609,30 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory } } } + if (p_options.has("retarget/rest_fixer/reset_all_bone_poses_after_import") && !bool(p_options["retarget/rest_fixer/reset_all_bone_poses_after_import"])) { + // If Reset All Bone Poses After Import is disabled, preserve the original bone pose, adjusted for the new bone rolls. + for (int bone_idx = 0; bone_idx < src_skeleton->get_bone_count(); bone_idx++) { + Transform3D old_rest = old_skeleton_rest[bone_idx]; + Transform3D new_rest = src_skeleton->get_bone_rest(bone_idx); + Transform3D old_pg; + Transform3D new_pg; + int parent_idx = src_skeleton->get_bone_parent(bone_idx); + if (parent_idx >= 0) { + old_pg = old_skeleton_global_rest[parent_idx]; + new_pg = src_skeleton->get_bone_global_rest(parent_idx); + } + + Quaternion old_pg_q = old_pg.basis.get_rotation_quaternion(); + Quaternion new_pg_q = new_pg.basis.get_rotation_quaternion(); + Quaternion qt = src_skeleton->get_bone_pose_rotation(bone_idx); + src_skeleton->set_bone_pose_rotation(bone_idx, new_pg_q.inverse() * old_pg_q * qt * old_rest.basis.get_rotation_quaternion().inverse() * old_pg_q.inverse() * new_pg_q * new_rest.basis.get_rotation_quaternion()); + + Basis sc = Basis().scaled(src_skeleton->get_bone_pose_scale(bone_idx)); + src_skeleton->set_bone_pose_scale(bone_idx, (new_pg.basis.inverse() * old_pg.basis * sc * old_rest.basis.inverse() * old_pg.basis.inverse() * new_pg.basis * new_rest.basis).get_scale()); + Vector3 ps = src_skeleton->get_bone_pose_position(bone_idx); + src_skeleton->set_bone_pose_position(bone_idx, new_pg_q.xform_inv(old_pg_q.xform(ps - old_rest.origin)) + new_rest.origin); + } + } is_rest_changed = true; } @@ -669,12 +699,14 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory } } - // Init skeleton pose to new rest. - for (int i = 0; i < src_skeleton->get_bone_count(); i++) { - Transform3D fixed_rest = src_skeleton->get_bone_rest(i); - src_skeleton->set_bone_pose_position(i, fixed_rest.origin); - src_skeleton->set_bone_pose_rotation(i, fixed_rest.basis.get_rotation_quaternion()); - src_skeleton->set_bone_pose_scale(i, fixed_rest.basis.get_scale()); + if (!p_options.has("retarget/rest_fixer/reset_all_bone_poses_after_import") || bool(p_options["retarget/rest_fixer/reset_all_bone_poses_after_import"])) { + // Init skeleton pose to new rest. + for (int i = 0; i < src_skeleton->get_bone_count(); i++) { + Transform3D fixed_rest = src_skeleton->get_bone_rest(i); + src_skeleton->set_bone_pose_position(i, fixed_rest.origin); + src_skeleton->set_bone_pose_rotation(i, fixed_rest.basis.get_rotation_quaternion()); + src_skeleton->set_bone_pose_scale(i, fixed_rest.basis.get_scale()); + } } }