MRが楽しい

MRやVRについて学習したことを書き残す

Blender3.0で利用可能なpythonスクリプトを作る その134(アクションデータ内のカーブにスムージングを行う)

本日は Blender の技術調査枠です。
Blender3.0で利用可能なpythonスクリプトを作ります。

アクションデータ内のカーブにスムージングを行う

アクションデータ内のカーブにスムージングを行うには bpy.ops.graph.smooth オペレータを利用します。
docs.blender.org

bpy.ops.graph オペレータはグラフエディターでのみ有効です。
他のビューからオペレータを操作する場合は以下の例のようにグラフエディターのコンテキストの参照(context)を取得する必要があります。

# 全エリアを確認してグラフエディターの参照を取得する
override_context = None
for area in bpy.context.screen.areas:
    if area.type == 'GRAPH_EDITOR':
        # context の参照を作成する
        override_context = bpy.context.copy()
        override_context["space_data"] = area.spaces[0]
        override_context["area"] = area
if override_context == None:
    return False

# 参照を渡してオペレータを実行する
bpy.ops.graph.smooth(override_context)

サンプルスクリプト

スクリプトを実行すると指定したカーブの全インデックスを選択して指定回数のスムージングを行い、カーブデータを滑らかにします。
・Script_update_keyframelist_smoothing.py

# bpyインポート
import bpy

# アクションに含まれるカーブを指定してスムージングをかける
def update_keyframelist_smoothing(arg_actionname:str,
  arg_datapathname:str, arg_datapathindex:int,
  arg_smoothingcount:int=1) -> bool:
    """アクションに含まれるカーブを指定してスムージングをかける

    Keyword Arguments:
        arg_actionname {str} -- 指定アクション名
        arg_datapathname {str} -- 指定データパス名
        arg_datapathindex {int} -- 指定インデックス
        arg_smoothingcount {int} -- スムージング回数

    Returns:
        bool -- 実行成否
    """

    # 指定名のアクションを取得する
    target_action = bpy.data.actions.get(arg_actionname)    
    if target_action == None:
        return False
    
    # 指定データパスのカーブを取得する
    # FCurvesアクセスのマニュアル
    # (https://docs.blender.org/api/current/bpy.types.ActionFCurves.html)
    target_curve = target_action.fcurves.find(arg_datapathname, index=arg_datapathindex)
    if target_curve == None:
        return False

    # bpy.ops.graph のオペレータはグラフエディターでのみ実行可能
    # 全エリアを確認してグラフエディターの参照を取得する
    override_context = None
    for area in bpy.context.screen.areas:
        if area.type == 'GRAPH_EDITOR':
            # context の参照を作成する
            override_context = bpy.context.copy()
            override_context["space_data"] = area.spaces[0]
            override_context["area"] = area
    if override_context == None:
        return False
    
    # カーブ内の全選択をいったん解除する
    bpy.ops.graph.select_all(override_context, action='DESELECT')

    # カーブ内の全キーポイントを走査する
    for keyframe_point in target_curve.keyframe_points:
        # キーフレーム内の全インデックスのコントロールポイントを選択状態にする
        # Keyframeアクセスのマニュアル
        # (https://docs.blender.org/api/current/bpy.types.Keyframe.html)
        keyframe_point.select_control_point = True

    # カーブに指定回数のスムージングを実行する
    for val in range(arg_smoothingcount):
        bpy.ops.graph.smooth(override_context)

    return True

# 関数の実行例
actionname = "CubeAction2"
datapathname = 'location'
datapathindex = 2 # ロケーションの場合 0:Xaxis, 1:Yaxis, 2:Zaxis の対応で値が保持されている
# アクションカーブにスムージングをかける
update_keyframelist_smoothing(arg_actionname=actionname,
  arg_datapathname=datapathname, arg_datapathindex=datapathindex,
  arg_smoothingcount=2)

・実行前

・実行後