Map NpcAvatar bone sync and proxy pivots to the Quaternius 62-joint names with old-rig fallback
This commit is contained in:
1 parent
e2f52fbfd1
commit
271f10ac4d
1 file changed
+31
-16
+31
-16
@@ -413,38 +413,38 @@ func _build_skinned_body(npc_type: int) -> bool:
|
|||||||
|
|
||||||
# Animation proxies: the existing _animate()/idle code drives these Node3D
|
# Animation proxies: the existing _animate()/idle code drives these Node3D
|
||||||
# pivots; _sync_skeleton() copies their rotations onto the armature bones.
|
# pivots; _sync_skeleton() copies their rotations onto the armature bones.
|
||||||
|
_bind_bones()
|
||||||
_head = Node3D.new()
|
_head = Node3D.new()
|
||||||
_head.name = "Head"
|
_head.name = "Head"
|
||||||
_head.position = Vector3(0, 1.62, 0)
|
_head.position = _rest_origin(["Head"])
|
||||||
_rig.add_child(_head)
|
_rig.add_child(_head)
|
||||||
for side in [-1.0, 1.0]:
|
for side in [-1.0, 1.0]:
|
||||||
var suffix := "L" if side < 0.0 else "R"
|
var suffix := "L" if side < 0.0 else "R"
|
||||||
var hip := Node3D.new()
|
var hip := Node3D.new()
|
||||||
hip.name = "Hip" + suffix
|
hip.name = "Hip" + suffix
|
||||||
hip.position = Vector3(0.13 * side, 0.64, 0)
|
hip.position = _rest_origin(["Hip" + suffix, "UpperLeg." + suffix])
|
||||||
_rig.add_child(hip)
|
_rig.add_child(hip)
|
||||||
var knee := Node3D.new()
|
var knee := Node3D.new()
|
||||||
knee.name = "Knee"
|
knee.name = "Knee"
|
||||||
knee.position = Vector3(0, -0.34, 0)
|
knee.position = _rest_origin(["Knee" + suffix, "LowerLeg." + suffix]) - hip.position
|
||||||
hip.add_child(knee)
|
hip.add_child(knee)
|
||||||
_legs.append(hip)
|
_legs.append(hip)
|
||||||
_knees.append(knee)
|
_knees.append(knee)
|
||||||
var shoulder := Node3D.new()
|
var shoulder := Node3D.new()
|
||||||
shoulder.name = "Shoulder" + suffix
|
shoulder.name = "Shoulder" + suffix
|
||||||
shoulder.position = Vector3(0.27 * side, 1.38, 0)
|
shoulder.position = _rest_origin(["Shoulder" + suffix, "UpperArm." + suffix])
|
||||||
_rig.add_child(shoulder)
|
_rig.add_child(shoulder)
|
||||||
var elbow := Node3D.new()
|
var elbow := Node3D.new()
|
||||||
elbow.name = "Elbow"
|
elbow.name = "Elbow"
|
||||||
elbow.position = Vector3(0, -0.30, 0)
|
elbow.position = _rest_origin(["Elbow" + suffix, "LowerArm." + suffix]) - shoulder.position
|
||||||
shoulder.add_child(elbow)
|
shoulder.add_child(elbow)
|
||||||
var hand := Node3D.new()
|
var hand := Node3D.new()
|
||||||
hand.name = "Hand"
|
hand.name = "Hand"
|
||||||
hand.position = Vector3(0, -0.30, 0.02)
|
hand.position = _rest_origin(["Hand" + suffix, "Wrist." + suffix]) - elbow.position
|
||||||
elbow.add_child(hand)
|
elbow.add_child(hand)
|
||||||
_arms.append(shoulder)
|
_arms.append(shoulder)
|
||||||
_elbows.append(elbow)
|
_elbows.append(elbow)
|
||||||
_hands.append(hand)
|
_hands.append(hand)
|
||||||
_bind_bones()
|
|
||||||
|
|
||||||
_add_accessory(str(outfit["accessory"]), cloth)
|
_add_accessory(str(outfit["accessory"]), cloth)
|
||||||
_add_character_gear()
|
_add_character_gear()
|
||||||
@@ -495,27 +495,42 @@ func _bind_bones() -> void:
|
|||||||
for index in _skeleton.get_bone_count():
|
for index in _skeleton.get_bone_count():
|
||||||
_bone_indices[_skeleton.get_bone_name(index)] = index
|
_bone_indices[_skeleton.get_bone_name(index)] = index
|
||||||
|
|
||||||
|
## First-found rest origin for a list of candidate bone names. Lets the proxy
|
||||||
|
## pivots track the actual skeleton (old 13-core or Quaternius 62-joint).
|
||||||
|
func _rest_origin(names: Array) -> Vector3:
|
||||||
|
if _skeleton == null:
|
||||||
|
return Vector3.ZERO
|
||||||
|
for bone_name in names:
|
||||||
|
if _bone_indices.has(bone_name):
|
||||||
|
return _skeleton.get_bone_rest(_bone_indices[bone_name]).origin
|
||||||
|
return Vector3.ZERO
|
||||||
|
|
||||||
## Copy the proxy pivot rotations onto armature bones. Limb bones point down, so
|
## Copy the proxy pivot rotations onto armature bones. Limb bones point down, so
|
||||||
## an X rotation swings them forward/back; the Head bone points up, so a Y
|
## an X rotation swings them forward/back; the Head bone points up, so a Y
|
||||||
## rotation is the look yaw.
|
## rotation is the look yaw. The Quaternius rig uses dot-suffixed names
|
||||||
|
## (UpperLeg.L, UpperArm.L, ...); the old 13-core rig uses HipL/ShoulderL, so
|
||||||
|
## both are tried and the first one present in the skeleton wins.
|
||||||
func _sync_skeleton() -> void:
|
func _sync_skeleton() -> void:
|
||||||
if _skeleton == null or _bone_indices.is_empty():
|
if _skeleton == null or _bone_indices.is_empty():
|
||||||
return
|
return
|
||||||
var names := ["HipL", "HipR"]
|
|
||||||
for i in 2:
|
for i in 2:
|
||||||
_pose_bone(names[i], _legs[i].rotation.x, Vector3.RIGHT)
|
_pose_bone_any(["UpperLeg.L", "HipL"], ["UpperLeg.R", "HipR"], i, _legs[i].rotation.x)
|
||||||
names = ["KneeL", "KneeR"]
|
|
||||||
for i in 2:
|
for i in 2:
|
||||||
_pose_bone(names[i], _knees[i].rotation.x, Vector3.RIGHT)
|
_pose_bone_any(["LowerLeg.L", "KneeL"], ["LowerLeg.R", "KneeR"], i, _knees[i].rotation.x)
|
||||||
names = ["ShoulderL", "ShoulderR"]
|
|
||||||
for i in 2:
|
for i in 2:
|
||||||
_pose_bone(names[i], _arms[i].rotation.x, Vector3.RIGHT)
|
_pose_bone_any(["UpperArm.L", "ShoulderL"], ["UpperArm.R", "ShoulderR"], i, _arms[i].rotation.x)
|
||||||
names = ["ElbowL", "ElbowR"]
|
|
||||||
for i in 2:
|
for i in 2:
|
||||||
_pose_bone(names[i], _elbows[i].rotation.x, Vector3.RIGHT)
|
_pose_bone_any(["LowerArm.L", "ElbowL"], ["LowerArm.R", "ElbowR"], i, _elbows[i].rotation.x)
|
||||||
if _head != null:
|
if _head != null:
|
||||||
_pose_bone("Head", _head.rotation.y, Vector3.UP)
|
_pose_bone("Head", _head.rotation.y, Vector3.UP)
|
||||||
|
|
||||||
|
func _pose_bone_any(left: Array, right: Array, index: int, angle: float) -> void:
|
||||||
|
var names: Array = left if index == 0 else right
|
||||||
|
for bone_name in names:
|
||||||
|
if _bone_indices.has(bone_name):
|
||||||
|
_pose_bone(bone_name, angle, Vector3.RIGHT)
|
||||||
|
return
|
||||||
|
|
||||||
func _pose_bone(bone_name: String, angle: float, axis: Vector3) -> void:
|
func _pose_bone(bone_name: String, angle: float, axis: Vector3) -> void:
|
||||||
if not _bone_indices.has(bone_name):
|
if not _bone_indices.has(bone_name):
|
||||||
return
|
return
|
||||||
|
|||||||
Reference in new issue
Block a user