Browse Source

Merge pull request #52462 from TokageItLab/fixed-regression-of-skinning

Fixed regression of skinning with skeleton
Juan Linietsky 4 years ago
parent
commit
25291a5b03
2 changed files with 19 additions and 15 deletions
  1. 5 7
      editor/plugins/node_3d_editor_gizmos.cpp
  2. 14 8
      scene/3d/skeleton_3d.cpp

+ 5 - 7
editor/plugins/node_3d_editor_gizmos.cpp

@@ -2097,7 +2097,6 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 	Color bonecolor = Color(1.0, 0.4, 0.4, 0.3);
 	Color bonecolor = Color(1.0, 0.4, 0.4, 0.3);
 	Color rootcolor = Color(0.4, 1.0, 0.4, 0.1);
 	Color rootcolor = Color(0.4, 1.0, 0.4, 0.1);
 
 
-	//LocalVector<int> bones_to_process = skel->get_parentless_bones();
 	LocalVector<int> bones_to_process;
 	LocalVector<int> bones_to_process;
 	bones_to_process = skel->get_parentless_bones();
 	bones_to_process = skel->get_parentless_bones();
 
 
@@ -2109,19 +2108,18 @@ void Skeleton3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) {
 		child_bones_vector = skel->get_bone_children(current_bone_idx);
 		child_bones_vector = skel->get_bone_children(current_bone_idx);
 		int child_bones_size = child_bones_vector.size();
 		int child_bones_size = child_bones_vector.size();
 
 
-		// You have children but no parent, then you must be a root/parentless bone.
-		if (child_bones_size >= 0 && skel->get_bone_parent(current_bone_idx) <= 0) {
-			grests[current_bone_idx] = skel->global_pose_to_local_pose(current_bone_idx, skel->get_bone_global_pose(current_bone_idx));
+		if (skel->get_bone_parent(current_bone_idx) < 0) {
+			grests[current_bone_idx] = skel->get_bone_rest(current_bone_idx);
 		}
 		}
 
 
 		for (int i = 0; i < child_bones_size; i++) {
 		for (int i = 0; i < child_bones_size; i++) {
 			int child_bone_idx = child_bones_vector[i];
 			int child_bone_idx = child_bones_vector[i];
 
 
-			grests[child_bone_idx] = skel->global_pose_to_local_pose(child_bone_idx, skel->get_bone_global_pose(child_bone_idx));
+			grests[child_bone_idx] = grests[current_bone_idx] * skel->get_bone_rest(child_bone_idx);
 			Vector3 v0 = grests[current_bone_idx].origin;
 			Vector3 v0 = grests[current_bone_idx].origin;
 			Vector3 v1 = grests[child_bone_idx].origin;
 			Vector3 v1 = grests[child_bone_idx].origin;
-			Vector3 d = skel->get_bone_rest(child_bone_idx).origin.normalized();
-			real_t dist = skel->get_bone_rest(child_bone_idx).origin.length();
+			Vector3 d = (v1 - v0).normalized();
+			real_t dist = v0.distance_to(v1);
 
 
 			// Find closest axis.
 			// Find closest axis.
 			int closest = -1;
 			int closest = -1;

+ 14 - 8
scene/3d/skeleton_3d.cpp

@@ -896,19 +896,25 @@ Ref<SkinReference> Skeleton3D::register_skin(const Ref<Skin> &p_skin) {
 		int len = bones.size();
 		int len = bones.size();
 
 
 		// calculate global rests and invert them
 		// calculate global rests and invert them
-		Vector<int> bones_to_process = get_parentless_bones();
+		LocalVector<int> bones_to_process;
+		bones_to_process = get_parentless_bones();
 		while (bones_to_process.size() > 0) {
 		while (bones_to_process.size() > 0) {
 			int current_bone_idx = bones_to_process[0];
 			int current_bone_idx = bones_to_process[0];
-			bones_to_process.erase(current_bone_idx);
 			const Bone &b = bonesptr[current_bone_idx];
 			const Bone &b = bonesptr[current_bone_idx];
-
-			// Note: the code below may not work by default. May need to track an integer for the bone pose index order
-			// in the while loop, instead of using current_bone_idx.
-			if (b.parent >= 0) {
-				skin->set_bind_pose(current_bone_idx, skin->get_bind_pose(b.parent) * b.rest);
-			} else {
+			bones_to_process.erase(current_bone_idx);
+			LocalVector<int> child_bones_vector;
+			child_bones_vector = get_bone_children(current_bone_idx);
+			int child_bones_size = child_bones_vector.size();
+			if (b.parent < 0) {
 				skin->set_bind_pose(current_bone_idx, b.rest);
 				skin->set_bind_pose(current_bone_idx, b.rest);
 			}
 			}
+			for (int i = 0; i < child_bones_size; i++) {
+				int child_bone_idx = child_bones_vector[i];
+				const Bone &cb = bonesptr[child_bone_idx];
+				skin->set_bind_pose(child_bone_idx, skin->get_bind_pose(current_bone_idx) * cb.rest);
+				// Add the bone's children to the list of bones to be processed.
+				bones_to_process.push_back(child_bones_vector[i]);
+			}
 		}
 		}
 
 
 		for (int i = 0; i < len; i++) {
 		for (int i = 0; i < len; i++) {