Blender上でテキストベースでベジェ曲線を操作するための手法についてまとめておく。

ベジェ曲線は通常のメッシュのように、辺や面、頂点を選択するようには編集ができず、
  • 編集点の選択
  • 編集点に対応するハンドルの選択
  • 移動、回転、延長
のような手順を踏んで変形を行う。


動作確認環境 : Blender 4.2


ベジェ曲線操作のための要素選択処理


ベジエ曲線の移動、回転、延長などの操作を行う上で、編集を行うポイント選択する必要があります。それらの処理を次のようにまとめました。

メッシュ操作時の選択方法と比較すると、違いが分かりやすいです。

▼関連記事 : メッシュ要素選択


Python :
def bezier_point_select(
    element_list,                # 選択ポイント、ハンドルリスト
    select_mode='CONTROL_POINT', # 選択モード(CONTROL_POINT/HANDLE_LEFT/HANDLE_RIGHT)
    object_name_list=["NaN"]     # オブジェクト名
):
    # 現在のモード保存
    current_mode = bpy.context.object.mode
    if object_name_list[0] != "NaN":
        for object_name in object_name_list:
            # 現在のアクティブオブジェクト選択
            obj = bpy.data.objects.get(object_name)
            if obj:
                obj.select_set(True)
                bpy.context.view_layer.objects.active = obj
    # アクティブオブジェクト取得
    obj = bpy.context.object
    # カーブオブジェクト確認
    if obj and obj.type == 'CURVE':
        # モード切り替え
        bpy.ops.object.mode_set(mode='EDIT')
        # カーブデータ取得
        curve = obj.data
        # 全ポイント選択解除
        for spline in curve.splines:
            if spline.type == 'BEZIER':
                for bezier_point in spline.bezier_points:
                    bezier_point.select_control_point = False
                    bezier_point.select_left_handle = False
                    bezier_point.select_right_handle = False
        # 指定ポイント/ハンドル選択
        for idx in element_list:
            for spline in curve.splines:
                if spline.type == 'BEZIER':
                    if idx < len(spline.bezier_points):
                        bezier_point = spline.bezier_points[idx]
                        if select_mode == 'CONTROL_POINT':
                            bezier_point.select_control_point = True
                        elif select_mode == 'HANDLE_LEFT':
                            bezier_point.select_left_handle = True
                        elif select_mode == 'HANDLE_RIGHT':
                            bezier_point.select_right_handle = True
    else:
        print("No curve object selected.")
    # 元のモードに戻す
    bpy.ops.object.mode_set(mode=current_mode)

02行目 :
ベジェ曲線のどのインデックスを指定します。
課題は、3D View上にどの点がどのインデックスに当たるのか表示できないため、いくつか選択状態にすることで該当ポイントを探るしかないことです。

03行目 :
選択したインデックスの「左ハンドル」「右ハンドル」「中心コントロールポイント」の内、指定する位置を指定します。

こちらの画像のようなハンドルを選択し、移動や回転の処理を加えることでベシェ曲線を変形していきます。


ベジェ曲線の変形操作例


ベジエ曲線を変形して、以下の画像のフックようなオブジェクトを生成する手順を例として示します。

ベジエ曲線の変形後、"bevel_depth"の値を調整して、カーブオブジェクトに厚みをつけています。

Python :
def Base_create():
    bpy.ops.object.mode_set(mode='OBJECT')

    # ベジェ追加
    bpy.ops.curve.primitive_bezier_curve_add(
        radius=1
    ,   enter_editmode=False
    ,   align='WORLD'
    ,   location=(0, 0, 2)
    ,   scale=(1, 1, 1)
    )
    # 名前を設定
    bpy.context.object.name = "flame_00"

    # 回転
    object_rotate_func(
        object_list=["flame_00"]
    ,   transform_pivot_point="INDIVIDUAL_ORIGINS"
    ,   radians_num=-90
    ,   orient_axis="X"
    ,   orient_type="GLOBAL"
    )

    # Mode切り替え
    bpy.ops.object.mode_set(mode='OBJECT')
    bpy.ops.object.mode_set(mode='EDIT')

    # ベジエ曲線(ハンドル/コントロールポイント選択)
    # 中心 : CONTROL_POINT, 右手 : HANDLE_RIGHT、左手 : HANDLE_LEFT
    bezier_point_select(
        element_list=[0],               # ポイントインデックス
        select_mode='CONTROL_POINT',    # コントロールポイント
        object_name_list=["flame_00"]   # 名前
    )

    # ベジェ曲線 延長
    bpy.ops.curve.extrude_move(
        CURVE_OT_extrude={
            "mode":'TRANSLATION'
        }
    ,   TRANSFORM_OT_translate={
            "value":(-0.1, 0, 0.5)
    ,       "orient_type":'GLOBAL'
        }
    )
    # オブジェクトサイズ変更
    common_var = 0.7
    bpy.ops.transform.resize(
        value=(common_var, common_var, common_var)
    ,   orient_type='GLOBAL'
    )
    # 要素回転
    bpy.ops.transform.rotate(
        value=math.radians(-155)
    ,   orient_axis='Y'
    ,   orient_type='GLOBAL'
    )
    # オブジェクト移動
    bpy.ops.transform.translate(
        value=(-0.90, 0, -0.15)
    ,   orient_type='GLOBAL'
    )

    # ベジェ曲線 延長
    bpy.ops.curve.extrude_move(
        CURVE_OT_extrude={
            "mode":'TRANSLATION'
        }
    ,   TRANSFORM_OT_translate={
            "value":(-0.1, 0, 0)
    ,       "orient_type":'GLOBAL'
        }
    )
    # 要素回転
    bpy.ops.transform.rotate(
        value=math.radians(-135)
    ,   orient_axis='Y'
    ,   orient_type='GLOBAL'
    )
    # オブジェクト移動
    bpy.ops.transform.translate(
        value=(1.1, 0, -0.05)
    ,   orient_type='GLOBAL'
    )

    # Mode切り替え
    bpy.ops.object.mode_set(mode='OBJECT')

    # ベベル
    bpy.context.object.data.bevel_depth = 0.12

Base_create()

05行目 :
カーブオブジェクト(ベジエ曲線)の追加

16行目 :
▼object_rotate_func


30行目 :
ベジエ曲線の操作位置、およびハンドルの選択

以上

このエントリーをはてなブックマークに追加
コメントを閉じる

コメント

コメントフォーム
記事の評価
  • リセット
  • リセット