Determining relative rotation difference from skeleton to physical bone
Asked Answered
B

2

0

Apologies for the bad title:

I am trying to make an active ragdoll system. I have a Skeleton3D that I've generated the physical skeleton for, with a copy that plays a target animation that I would like the ragdoll to mimic, by using the angular springs on the 6DOF joints (this might not currently work with GODOT physics, but the angular springs work with Jolt - not relevant to the question either way).

I can not for the life of me figure out how to translate the rotational difference from the skeleton's pose to the joint's target. Getting the rotational difference in the bone's local space is easy, but translating that to the PhysicalBone3D's space has me stumped.

Is someone here a rotational genius that can figure this out?

Secondly - is there a resource out there that explains how the Create Physical Bones process actually works or would I have to go read the source? From how the nodes are laid out, you would assume that the initial transform of each physical bone should be equal to the get_bone_global_rest for that bone, but that is not the case.

Buiron answered 1/10, 2023 at 20:46 Comment(0)
B
0

OK... after much trial and tribulation, I found an answer, not sure if it's good but:

Basically, we transform the rest pose to 'world' space (i.e. relative to the parent node, same as the skeleton's root), and then transform it into the local space of the joint. Then do the same for the current pose, then find the difference between those two rotations. I've sure it can be optimised but this works.

if target_skeleton.get_bone_parent(b.get_bone_id()) > -1:
			var bone_basis =  target_skeleton.get_bone_rest(b.get_bone_id()).basis
			var jt : Transform3D = b.get("joint_offset") 
			
		var parent_bone = target_skeleton.get_bone_parent(b.get_bone_id())
		var parent_rest_global = target_skeleton.get_bone_global_rest(parent_bone).basis
		
		var target_local_pose : Basis = target_skeleton.get_bone_pose(b.get_bone_id()).basis
		var global_rest : Basis = target_skeleton.get_bone_global_rest(b.get_bone_id()).basis
		

		var pose_worldspace = parent_rest_global * target_local_pose
		var rotation_difference_worldspace = pose_worldspace * global_rest.inverse()
		
		var rest_jointspace =  initial_rotations[b].inverse() * global_rest
		var pose_jointspace = initial_rotations[b].inverse() * pose_worldspace
		
		var jointspace_difference = pose_jointspace * rest_jointspace.inverse()

Buiron answered 2/10, 2023 at 12:6 Comment(0)
N
0

Buiron As you found a solution I've marked it as best answer. 👍

Noontime answered 2/10, 2023 at 14:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.