blender python api -修改骨架中特定骨骼的變換,包括沿不同軸的旋轉、位置和縮放(旋轉為四元數運算WXYZ)

大话人生發表於2024-04-19

1.選中骨架,進入姿態模式,

2.執行程式碼

程式碼:

import bpy
import mathutils
import math



def modify_bone_transformations(armature_name, bone_name, rotation_axes, angles_degrees, new_location, new_scale, frame_start, frame_end):
    """
    修改骨架中特定骨骼的變換,包括沿不同軸的旋轉、位置和縮放。

    引數:
    armature_name -- 骨架物件的名稱
    bone_name -- 骨骼的名稱
    rotation_axes -- 一個包含三個向量的物件,分別對應X、Y、Z軸的旋轉軸
    angles_degrees -- 與rotation_axes對應的旋轉角度
    new_location -- 新位置的 Vector 物件
    new_scale -- 新縮放的 Vector 物件
    frame_start -- 起始幀
    frame_end -- 結束幀
    """
    # 獲取骨架物件
    armature = bpy.data.objects.get(armature_name)
    if armature is None or armature.type != 'ARMATURE':
        print(f"未找到骨架物件 '{armature_name}' 或物件型別不是骨架。")
        return

    # 獲取骨架的動作資料
    action = armature.animation_data.action
    if action is None:
        print("骨架沒有動作資料。")
        return

    # 獲取特定骨骼的姿勢物件
    pose_bone = armature.pose.bones.get(bone_name)
    if pose_bone is None:
        print(f"在骨架中未找到名為 '{bone_name}' 的骨骼。")
        return

    # 遍歷指定的幀範圍
    for frame in range(frame_start, frame_end + 1):
        # 初始化總的四元數為單位四元數(無旋轉)
        total_rotation_quat = mathutils.Quaternion((1, 0, 0, 0))

        # 為每個軸的旋轉建立四元數並累加
        for axis, angle in zip(rotation_axes, angles_degrees):
            if angle != 0:
                # 將角度轉換為弧度並建立四元數
                rotation_quat = mathutils.Quaternion(axis, math.radians(angle))
                # 將新旋轉應用到總的四元數上
                total_rotation_quat = total_rotation_quat @ rotation_quat

        # 設定骨骼的變換
        pose_bone.rotation_quaternion = total_rotation_quat
        pose_bone.location = new_location
        pose_bone.scale = new_scale

        # 插入關鍵幀
        pose_bone.keyframe_insert(data_path="rotation_quaternion", frame=frame)
        pose_bone.keyframe_insert(data_path="location", frame=frame)
        pose_bone.keyframe_insert(data_path="scale", frame=frame)

    # 設定關鍵幀的插值模式為'CONSTANT'
    for fcurve in action.fcurves:
        if fcurve.data_path.startswith(f"pose.bones['{bone_name}']"):
            fcurve.keyframe_points.foreach_set("interpolation", 'CONSTANT')

    print(f"骨骼 '{bone_name}' 的變換已從幀 {frame_start} 到 {frame_end} 更新。")

# 示例使用
armature_name = "Armature"
bone_name = "mixamorig:Hips"
rotation_axes = [(1, 0, 0), (0, 1, 0), (0, 0, 1)]  # 分別繞X、Y、Z軸
angles_degrees = [70, 50, 60]  # 分別對應上面的軸的旋轉角度
new_location = mathutils.Vector((0, 0, 0))
new_scale = mathutils.Vector((1, 1, 1))
frame_start = 1
frame_end = 60

# 呼叫函式修改骨骼的變換
modify_bone_transformations(armature_name, bone_name, rotation_axes, angles_degrees, new_location, new_scale, frame_start, frame_end)

# 提示使用者檢查Blender中的更改
print("請檢查Blender檢視更改。")

相關文章