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行目 :
ベジエ曲線の操作位置、およびハンドルの選択
以上