Python API: expose the math mapping vertex positions to B-Bone segments.

Recently a user expressed interest in exporting baked animation
with B-Bone segments. Currently the python API already exposes
segment matrices via a PoseBone method, but there is no access
to the mapping of vertices to the segments.

Although currently the math is simple and easy to re-implement,
forcing Python add-ons to do that would cause a maintenance issue
if the mapping is ever changed later (it's quite dumb, ignoring
the rest pose curve, and there definitely is room for improvement).

This patch extracts the relevant math into a BKE function, and
exposes it in the python API as a new PoseBone method.

Pull Request: https://projects.blender.org/blender/blender/pulls/105419
This commit is contained in:
Alexander Gavrilov
2023-03-03 20:44:35 +02:00
committed by Gitea
parent 0d7b0045c6
commit 36c6bcca1a
6 changed files with 127 additions and 23 deletions

View File

@@ -0,0 +1,34 @@
"""
This example shows how to use B-Bone segment matrices to emulate deformation
produced by the Armature modifier or constraint when assigned to the given bone
(without Preserve Volume). The coordinates are processed in armature Pose space:
"""
def bbone_deform_matrix(pose_bone, point):
index, blend_next = pose_bone.bbone_segment_index(point)
rest1 = pose_bone.bbone_segment_matrix(index, rest=True)
pose1 = pose_bone.bbone_segment_matrix(index, rest=False)
deform1 = pose1 @ rest1.inverted()
# bbone_segment_index ensures that index + 1 is always valid
rest2 = pose_bone.bbone_segment_matrix(index + 1, rest=True)
pose2 = pose_bone.bbone_segment_matrix(index + 1, rest=False)
deform2 = pose2 @ rest2.inverted()
deform = deform1 * (1 - blend_next) + deform2 * blend_next
return pose_bone.matrix @ deform @ pose_bone.bone.matrix_local.inverted()
# Armature modifier deforming vertices:
mesh = bpy.data.objects["Mesh"]
pose_bone = bpy.data.objects["Armature"].pose.bones["Bone"]
for vertex in mesh.data.vertices:
vertex.co = bbone_deform_matrix(pose_bone, vertex.co) @ vertex.co
# Armature constraint modifying an object transform:
empty = bpy.data.objects["Empty"]
matrix = empty.matrix_world
empty.matrix_world = bbone_deform_matrix(pose_bone, matrix.translation) @ matrix