Files
workinf_Blender_Wasm/tools/web/generate-pose-constraint-fixture.py
2026-08-12 04:47:48 -04:00

131 lines
5.2 KiB
Python

import math
import sys
import bpy
def keyframe_rotation(target, frame, degrees):
target.rotation_euler[2] = math.radians(degrees)
target.keyframe_insert(data_path="rotation_euler", index=2, frame=frame)
def main(output_path: str) -> None:
bpy.ops.wm.read_factory_settings(use_empty=True)
mesh = bpy.data.meshes.new("PoseConstraintMesh")
mesh.from_pydata(
[(-1.0, -1.0, 0.0), (1.0, -1.0, 0.0), (1.0, 1.0, 0.0), (-1.0, 1.0, 0.0)],
[],
[(0, 1, 2), (0, 2, 3)],
)
mesh.update()
mesh_object = bpy.data.objects.new("PoseConstraintMeshObject", mesh)
bpy.context.collection.objects.link(mesh_object)
mesh_object.location = (0.35, -0.2, 0.15)
mesh_object.rotation_euler = (math.radians(7.0), math.radians(-11.0), math.radians(5.0))
mesh_object.scale = (1.2, 0.8, 1.1)
scaled_parent = bpy.data.objects.new("ScaledRigParent", None)
bpy.context.collection.objects.link(scaled_parent)
scaled_parent.location = (-0.25, 0.3, 0.1)
scaled_parent.rotation_euler = (math.radians(4.0), math.radians(3.0), math.radians(-8.0))
scaled_parent.scale = (1.35, 0.7, 1.15)
armature_data = bpy.data.armatures.new("PoseConstraintArmature")
armature_object = bpy.data.objects.new("PoseConstraintArmatureObject", armature_data)
bpy.context.collection.objects.link(armature_object)
armature_object.parent = scaled_parent
armature_object.location = (-0.15, 0.1, -0.05)
armature_object.rotation_euler = (math.radians(-6.0), math.radians(9.0), math.radians(12.0))
armature_object.scale = (0.9, 1.1, 1.05)
bpy.context.view_layer.objects.active = armature_object
armature_object.select_set(True)
bpy.ops.object.mode_set(mode="EDIT")
root = armature_data.edit_bones.new("Root")
root.head = (0.0, 0.0, 0.0)
root.tail = (0.0, 0.0, 1.0)
mid = armature_data.edit_bones.new("Mid")
mid.head = (0.0, 0.0, 1.0)
mid.tail = (0.0, 0.0, 2.0)
mid.parent = root
mid.use_connect = True
tip = armature_data.edit_bones.new("Tip")
tip.head = (0.0, 0.0, 2.0)
tip.tail = (0.0, 0.0, 3.0)
tip.parent = mid
tip.use_connect = True
auxiliary = armature_data.edit_bones.new("Auxiliary")
auxiliary.head = (0.5, 0.0, 0.5)
auxiliary.tail = (0.5, 0.0, 1.25)
auxiliary.parent = root
bpy.ops.object.mode_set(mode="POSE")
pose_root = armature_object.pose.bones["Root"]
pose_root.rotation_mode = "XYZ"
for frame, degrees in ((1, 0.0), (5, 18.0), (10, 36.0), (15, 48.0)):
pose_root.rotation_euler[1] = math.radians(degrees)
pose_root.keyframe_insert(data_path="rotation_euler", index=1, frame=frame)
bpy.ops.object.mode_set(mode="OBJECT")
target = bpy.data.objects.new("PoseConstraintTarget", None)
bpy.context.collection.objects.link(target)
target.location = (0.0, 0.0, 1.0)
for frame, degrees in ((1, 0.0), (5, 35.0), (10, 70.0), (15, 95.0)):
keyframe_rotation(target, frame, degrees)
copy_rotation = armature_object.pose.bones["Auxiliary"].constraints.new("COPY_ROTATION")
copy_rotation.name = "Animated Copy Rotation"
copy_rotation.target = target
copy_rotation.owner_space = "WORLD"
copy_rotation.target_space = "WORLD"
copy_rotation.use_x = False
copy_rotation.use_y = False
copy_rotation.use_z = True
copy_rotation.influence = 0.75
ik_target = bpy.data.objects.new("PoseIKTarget", None)
bpy.context.collection.objects.link(ik_target)
pole_target = bpy.data.objects.new("PoseIKPole", None)
bpy.context.collection.objects.link(pole_target)
pole_target.location = (1.5, -1.0, 1.25)
for frame, location in (
(1, (0.35, 0.15, 2.65)),
(5, (0.75, 0.25, 2.45)),
(10, (1.0, -0.15, 2.15)),
(15, (0.45, -0.55, 2.55)),
):
ik_target.location = location
ik_target.keyframe_insert(data_path="location", frame=frame)
ik = armature_object.pose.bones["Tip"].constraints.new("IK")
ik.name = "Animated Two Bone IK"
ik.target = ik_target
ik.pole_target = pole_target
ik.chain_count = 2
ik.iterations = 128
ik.influence = 0.85
root_group = mesh_object.vertex_groups.new(name="Root")
mid_group = mesh_object.vertex_groups.new(name="Mid")
tip_group = mesh_object.vertex_groups.new(name="Tip")
auxiliary_group = mesh_object.vertex_groups.new(name="Auxiliary")
root_group.add([0, 1], 1.0, "REPLACE")
root_group.add([2, 3], 0.25, "REPLACE")
mid_group.add([0, 1], 0.0, "REPLACE")
mid_group.add([2, 3], 0.35, "REPLACE")
tip_group.add([0, 1], 0.0, "REPLACE")
tip_group.add([2, 3], 0.40, "REPLACE")
auxiliary_group.add([0, 1, 2, 3], 0.05, "REPLACE")
armature_modifier = mesh_object.modifiers.new(name="Armature Deform", type="ARMATURE")
armature_modifier.object = armature_object
scene = bpy.context.scene
scene.frame_start = 1
scene.frame_end = 15
scene.frame_set(1)
bpy.ops.wm.save_as_mainfile(filepath=output_path, compress=True)
if __name__ == "__main__":
if "--" not in sys.argv or len(sys.argv) <= sys.argv.index("--") + 1:
raise SystemExit("usage: blender -b --python generate-pose-constraint-fixture.py -- output.blend")
main(sys.argv[sys.argv.index("--") + 1])