Ver código fonte

Merge pull request #77123 from lyuma/child_mesh_retarget

Adjust BoneAttachment3D children/meshes during rest fixer
Rémi Verschelde 2 anos atrás
pai
commit
24a258d8a0

+ 35 - 47
editor/import/post_import_plugin_skeleton_rest_fixer.cpp

@@ -31,6 +31,7 @@
 #include "post_import_plugin_skeleton_rest_fixer.h"
 #include "post_import_plugin_skeleton_rest_fixer.h"
 
 
 #include "editor/import/scene_import_settings.h"
 #include "editor/import/scene_import_settings.h"
+#include "scene/3d/bone_attachment_3d.h"
 #include "scene/3d/importer_mesh_instance_3d.h"
 #include "scene/3d/importer_mesh_instance_3d.h"
 #include "scene/3d/skeleton_3d.h"
 #include "scene/3d/skeleton_3d.h"
 #include "scene/animation/animation_player.h"
 #include "scene/animation/animation_player.h"
@@ -105,42 +106,6 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 			global_transform.origin = Vector3(); // Translation by a Node is not a bone animation, so the retargeted model should be at the origin.
 			global_transform.origin = Vector3(); // Translation by a Node is not a bone animation, so the retargeted model should be at the origin.
 		}
 		}
 
 
-		// Calc IBM difference.
-		LocalVector<Vector<Transform3D>> ibm_diffs;
-		{
-			TypedArray<Node> nodes = p_base_scene->find_children("*", "ImporterMeshInstance3D");
-			while (nodes.size()) {
-				ImporterMeshInstance3D *mi = Object::cast_to<ImporterMeshInstance3D>(nodes.pop_back());
-				ERR_CONTINUE(!mi);
-
-				Ref<Skin> skin = mi->get_skin();
-				ERR_CONTINUE(!skin.is_valid());
-
-				Node *node = mi->get_node(mi->get_skeleton_path());
-				ERR_CONTINUE(!node);
-
-				Skeleton3D *mesh_skeleton = Object::cast_to<Skeleton3D>(node);
-				if (!mesh_skeleton || mesh_skeleton != src_skeleton) {
-					continue;
-				}
-
-				Vector<Transform3D> ibm_diff;
-				ibm_diff.resize(src_skeleton->get_bone_count());
-				Transform3D *ibm_diff_w = ibm_diff.ptrw();
-
-				int skin_len = skin->get_bind_count();
-				for (int i = 0; i < skin_len; i++) {
-					StringName bn = skin->get_bind_name(i);
-					int bone_idx = src_skeleton->find_bone(bn);
-					if (bone_idx >= 0) {
-						ibm_diff_w[bone_idx] = global_transform * src_skeleton->get_bone_global_rest(bone_idx) * skin->get_bind_pose(i);
-					}
-				}
-
-				ibm_diffs.push_back(ibm_diff);
-			}
-		}
-
 		// Apply node transforms.
 		// Apply node transforms.
 		if (bool(p_options["retarget/rest_fixer/apply_node_transforms"])) {
 		if (bool(p_options["retarget/rest_fixer/apply_node_transforms"])) {
 			Vector3 scl = global_transform.basis.get_scale_local();
 			Vector3 scl = global_transform.basis.get_scale_local();
@@ -288,12 +253,11 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 		Vector<Transform3D> silhouette_diff; // Transform values to be ignored when overwrite axis.
 		Vector<Transform3D> silhouette_diff; // Transform values to be ignored when overwrite axis.
 		silhouette_diff.resize(src_skeleton->get_bone_count());
 		silhouette_diff.resize(src_skeleton->get_bone_count());
 		Transform3D *silhouette_diff_w = silhouette_diff.ptrw();
 		Transform3D *silhouette_diff_w = silhouette_diff.ptrw();
+		LocalVector<Transform3D> pre_silhouette_skeleton_global_rest;
+		for (int i = 0; i < src_skeleton->get_bone_count(); i++) {
+			pre_silhouette_skeleton_global_rest.push_back(src_skeleton->get_bone_global_rest(i));
+		}
 		if (bool(p_options["retarget/rest_fixer/fix_silhouette/enable"])) {
 		if (bool(p_options["retarget/rest_fixer/fix_silhouette/enable"])) {
-			LocalVector<Transform3D> old_skeleton_global_rest;
-			for (int i = 0; i < src_skeleton->get_bone_count(); i++) {
-				old_skeleton_global_rest.push_back(src_skeleton->get_bone_global_rest(i));
-			}
-
 			Vector<int> bones_to_process = prof_skeleton->get_parentless_bones();
 			Vector<int> bones_to_process = prof_skeleton->get_parentless_bones();
 			while (bones_to_process.size() > 0) {
 			while (bones_to_process.size() > 0) {
 				int prof_idx = bones_to_process[0];
 				int prof_idx = bones_to_process[0];
@@ -450,7 +414,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 
 
 			// For skin modification in overwrite rest.
 			// For skin modification in overwrite rest.
 			for (int i = 0; i < src_skeleton->get_bone_count(); i++) {
 			for (int i = 0; i < src_skeleton->get_bone_count(); i++) {
-				silhouette_diff_w[i] = old_skeleton_global_rest[i] * src_skeleton->get_bone_global_rest(i).inverse();
+				silhouette_diff_w[i] = pre_silhouette_skeleton_global_rest[i] * src_skeleton->get_bone_global_rest(i).affine_inverse();
 			}
 			}
 
 
 			is_rest_changed = true;
 			is_rest_changed = true;
@@ -652,7 +616,9 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 					ERR_CONTINUE(!mi);
 					ERR_CONTINUE(!mi);
 
 
 					Ref<Skin> skin = mi->get_skin();
 					Ref<Skin> skin = mi->get_skin();
-					ERR_CONTINUE(!skin.is_valid());
+					if (skin.is_null()) {
+						continue;
+					}
 
 
 					Node *node = mi->get_node(mi->get_skeleton_path());
 					Node *node = mi->get_node(mi->get_skeleton_path());
 					ERR_CONTINUE(!node);
 					ERR_CONTINUE(!node);
@@ -662,20 +628,42 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory
 						continue;
 						continue;
 					}
 					}
 
 
-					Vector<Transform3D> ibm_diff = ibm_diffs[skin_idx];
-
 					int skin_len = skin->get_bind_count();
 					int skin_len = skin->get_bind_count();
 					for (int i = 0; i < skin_len; i++) {
 					for (int i = 0; i < skin_len; i++) {
 						StringName bn = skin->get_bind_name(i);
 						StringName bn = skin->get_bind_name(i);
 						int bone_idx = src_skeleton->find_bone(bn);
 						int bone_idx = src_skeleton->find_bone(bn);
 						if (bone_idx >= 0) {
 						if (bone_idx >= 0) {
-							Transform3D new_rest = silhouette_diff[bone_idx] * src_skeleton->get_bone_global_rest(bone_idx);
-							skin->set_bind_pose(i, new_rest.inverse() * ibm_diff[bone_idx]);
+							Transform3D adjust_transform = src_skeleton->get_bone_global_rest(bone_idx).affine_inverse() * silhouette_diff[bone_idx].affine_inverse() * pre_silhouette_skeleton_global_rest[bone_idx];
+							adjust_transform.scale(global_transform.basis.get_scale_local());
+							skin->set_bind_pose(i, adjust_transform * skin->get_bind_pose(i));
 						}
 						}
 					}
 					}
 
 
 					skin_idx++;
 					skin_idx++;
 				}
 				}
+				nodes = src_skeleton->get_children();
+				while (nodes.size()) {
+					BoneAttachment3D *attachment = Object::cast_to<BoneAttachment3D>(nodes.pop_back());
+					if (attachment == nullptr) {
+						continue;
+					}
+					int bone_idx = attachment->get_bone_idx();
+					if (bone_idx == -1) {
+						bone_idx = src_skeleton->find_bone(attachment->get_bone_name());
+					}
+					ERR_CONTINUE(bone_idx < 0 || bone_idx >= src_skeleton->get_bone_count());
+					Transform3D adjust_transform = src_skeleton->get_bone_global_rest(bone_idx).affine_inverse() * silhouette_diff[bone_idx].affine_inverse() * pre_silhouette_skeleton_global_rest[bone_idx];
+					adjust_transform.scale(global_transform.basis.get_scale_local());
+
+					TypedArray<Node> child_nodes = attachment->get_children();
+					while (child_nodes.size()) {
+						Node3D *child = Object::cast_to<Node3D>(child_nodes.pop_back());
+						if (child == nullptr) {
+							continue;
+						}
+						child->set_transform(adjust_transform * child->get_transform());
+					}
+				}
 			}
 			}
 
 
 			// Init skeleton pose to new rest.
 			// Init skeleton pose to new rest.