Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating bone rests in a Skeleton3D via code does not update the global rest as well #103623

Open
alexnikop opened this issue Mar 5, 2025 · 4 comments

Comments

@alexnikop
Copy link

alexnikop commented Mar 5, 2025

Tested versions

  • Reproducible in 4.4.0
  • Not reproducible in 4.3.0

System information

Windows 11 Godot Engine v4.4.stable.mono.official.4c311cbee Vulkan 1.3.289 - Forward+ - Using Device #0: NVIDIA - NVIDIA GeForce RTX 4070 SUPER

Issue description

Adding bones to a Skeleton3D via code does not update the global rest transform as well.

Steps to reproduce

  1. Create A Skeleton3D Node
  2. Add bones to the skeleton via code in a chain-like fashion (Every next bone is child of the previous one)
  3. Update the bone rests using set_bone_rest function
  4. Print global rests of all bones using get_bone_global_rest and see that global rests do not change

Minimal reproduction project (MRP)

extends Skeleton3D

func _ready() -> void:
	
	# number of bones to spawn
	var num_bones: int = 4
	
	# create sample transform 3D
	var transform: Transform3D = Transform3D.IDENTITY
	transform.origin = Vector3(0, 1, 0)
	
	for b in num_bones:
		# add bone in skeleton
		add_bone(str(b))
		# set bone rest
		set_bone_rest(b, transform)
		
		# set previous bone as parent bone
		if b > 0:
			set_bone_parent(b, b-1)
		
		# print bone rest and global rest
		print("**************")
		print(get_bone_rest(b))
		print(get_bone_global_rest(b))

This code above prints the following results:

**************
[X: (1.0, 0.0, 0.0), Y: (0.0, 1.0, 0.0), Z: (0.0, 0.0, 1.0), O: (0.0, 1.0, 0.0)]
[X: (1.0, 0.0, 0.0), Y: (0.0, 1.0, 0.0), Z: (0.0, 0.0, 1.0), O: (0.0, 0.0, 0.0)]
**************
[X: (1.0, 0.0, 0.0), Y: (0.0, 1.0, 0.0), Z: (0.0, 0.0, 1.0), O: (0.0, 1.0, 0.0)]
[X: (1.0, 0.0, 0.0), Y: (0.0, 1.0, 0.0), Z: (0.0, 0.0, 1.0), O: (0.0, 0.0, 0.0)]
**************
[X: (1.0, 0.0, 0.0), Y: (0.0, 1.0, 0.0), Z: (0.0, 0.0, 1.0), O: (0.0, 1.0, 0.0)]
[X: (1.0, 0.0, 0.0), Y: (0.0, 1.0, 0.0), Z: (0.0, 0.0, 1.0), O: (0.0, 0.0, 0.0)]
**************
[X: (1.0, 0.0, 0.0), Y: (0.0, 1.0, 0.0), Z: (0.0, 0.0, 1.0), O: (0.0, 1.0, 0.0)]
[X: (1.0, 0.0, 0.0), Y: (0.0, 1.0, 0.0), Z: (0.0, 0.0, 1.0), O: (0.0, 0.0, 0.0)]

The second line in every segment is the global bone rest. As you can see the origin of the transforms does not update

@Alex2782
Copy link
Member

Alex2782 commented Mar 5, 2025

Tested and reproduced.

blame Skeleton3D::set_bone_parent

maybe PR: #97744

@Drac32Drac
Copy link

I just spent the past few days struggling with this one. I can confirm that this bug exists in 4.4.0

Is there a workaround to this? Or alternatively a way to simply apply the entire current pose to the rest pose?
The editor button that applies the entire current pose to the rest pose seems to work. But that function as best I can tell isn't accessible from code.

@alexnikop
Copy link
Author

alexnikop commented Mar 15, 2025

As a workaround I calculate the global rest myself every time I create a new bone and save it in a dictionary. After that I can just retrieve any global rest from the dictionary when needed. Here is the relevant code to help you build a temporary solution until the issue is fixed.


Dictionary<int, Transform3D> boneGlobalRests;

public void SetSkeletonBoneGlobalRest(int boneIdx, Transform3D rest)
{
	int parentIdx = Skeleton.GetBoneParent(boneIdx);
	if (parentIdx == -1)
	{
		boneGlobalRests.Add(boneIdx, rest);
	}
	else
	{
		boneGlobalRests.Add(boneIdx, boneGlobalRests[parentIdx] * rest);
	}
}

Feel free to ask any more help on how to work around this

@Drac32Drac
Copy link

Drac32Drac commented Mar 15, 2025

I found another workaround that seems to work just fine.

Calculate and apply the LOCAL bone rests BEFORE parenting it to another bone and it updates the rests properly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants