こんにちは、管理人のウノケンです。
今回は、BlenderをPythonで自在に操作する方法について解説していきます。
Blenderは、3Dモデリングやアニメーション制作などに利用されるオープンソースの3Dアプリケーションです。Pythonとの親和性も高く、うまく使いこなすことができれば手作業による面倒な反復作業を自動化することが可能です。
この記事では、Pythonスクリプトを使ったBlenderの操作について、「編集モード」にフォーカスして解説していきます。3Dモデリング初心者の方や、Pythonになじみのない方でもコピペで操作を実行することができるので、ぜひ自分でも操作して自動化の利便性を感じてみてください。
なお、Blender Python APIについての解説や、Pythonスクリプトを使ったBlenderの基本操作については以下の記事で解説しています。
それでは見ていきましょう!
Blenderの「編集モード」をPythonで操作する方法
そもそもBlenderの編集モードとは
Blenderの編集モードとは、オブジェクトモードと並んで最も基本的な、3Dモデルを操作するためのモードです。3Dモデルの頂点、辺、面のいずれかを選択し、移動や回転、拡大・縮小、削除、追加などの操作を行うことができます。
オブジェクトモードと比較して、編集モードは3Dモデルのディテールや形状を調整したいときに重要な役割を果たします。
Blender Python APIの使い方
Blenderは、プログラミング言語であるPythonを使って多くの操作を自動化することが可能です。オブジェクトモードでメッシュを追加したり移動したりするだけでなく、編集モードに移行して修正を行うことも可能です。
Pythonを使ってBlenderの操作を行うための準備については以下の記事で詳しく紹介しています。Scriptingワークスペースに移動してテキストエディタを開いた状態までの操作がわからないという方は、以下の記事で確認しておきましょう。
Blenderの編集モードに関するPythonを使った基本操作7選【コピペ可能】
Pythonを使ったBlender編集モードの準備について紹介した後、基本操作を7つ取り上げて解説してきます。
以下の項目はすべてコピペで実行することが可能です。Blender初心者の方や、Pythonに不慣れな方もぜひ手元の環境で実行してみてください。
Pythonを使ったオブジェクトモードに関する基本操作は理解している前提で進めますので、不安のある方は「3Dモデリングを自動化!BlenderをPythonで操作する方法【コピペ可能】」の記事で復習しておきましょう。
基本操作の紹介の最後で、これらの編集モードで操作する自動化処理の例も掲載しています。
【準備】編集モード・オブジェクトモードの切り替え
「オブジェクトモード」から「編集モード」に切り替える際に使用するスクリプトは以下の通りです。
bpy.ops.object.mode_set(mode='EDIT')
余談になりますが、mode
引数を適切に設定することで「オブジェクトモード」に戻したり「スカルプトモード」等の他のモードに変更することも可能です。
- オブジェクトモード:
mode='OBJECT'
- スカルプトモード:
mode='SCULPT'
(参考:Object Mode Items — Blender Python API)
立方体を追加した後、編集モードに切り替える処理を実行するスクリプトは次のように記述されます。
import bpy
# デフォルトのメッシュを削除
for mesh in bpy.data.meshes:
bpy.data.meshes.remove(mesh)
# メッシュの追加
bpy.ops.mesh.primitive_cube_add()
# 編集モードに切り替え
bpy.ops.object.mode_set(mode='EDIT')
【準備】頂点・辺・面選択モードの切り替え
編集モードにおいて、「面選択モード」への切り替えを行うスクリプトは以下の通りです。
bpy.ops.mesh.select_mode(type='FACE')
同様に、「頂点選択モード」「辺選択モード」は引数を変更することで実現できます。
- 頂点選択モード:
type='VERT'
- 辺選択モード:
type='EDGE'
(参考:Mesh Select Mode Items — Blender Python API)
【準備】bmeshメッシュモジュールの使用
bmesh
モジュールを使用すると、メッシュの頂点や辺、ポリゴンなどの要素にアクセスして編集することができます。頂点の移動や追加、面の分割や削除といった操作が可能になります。
bmesh
の基本的な使用方法は以下の通りです。
bmesh
オブジェクトの作成
bmesh
モジュールをインポートし、bmesh
オブジェクトに変換します。
import bmesh
bm = bmesh.from_edit_mesh(bpy.context.object.data)
変更を反映
明示的に記述する必要がない場合もありますが、編集処理の変更を反映したい場合は以下の一文を挿入します。
bmesh.update_edit_mesh(bpy.context.object.data)
頂点の追加
座標(0,0,1)に頂点を追加するスクリプトは以下の通りです。
bm.verts.new((0, 0, 1))
辺の追加
辺を追加したい場合、2つの頂点を指定してbm.edges.new
を実行します。
座標(2.0, 2.0, 0.0), (2.0, -2.0, 0.0)の2点を結ぶ辺を追加するスクリプトは以下の通りです。
v1 = bm.verts.new((2.0, 2.0, 0.0))
v2 = bm.verts.new((2.0, -2.0, 0.0))
bm.edges.new((v1, v2))
面の追加
面を追加したい場合、4つの頂点を指定してbm.faces.new
を実行します。
座標(2.0, 2.0, 0.0), (2.0, -2.0, 0.0), (-2.0, -2.0, 0.0), (-2.0, 2.0, 0.0)の4点をからなる面を追加するスクリプトは以下の通りです。
v1 = bm.verts.new((2.0, 2.0, 0.0))
v2 = bm.verts.new((2.0, -2.0, 0.0))
v3 = bm.verts.new((-2.0, -2.0, 0.0))
v4 = bm.verts.new((-2.0, 2.0, 0.0))
bm.faces.new((v1, v2, v3, v4))
面の方向はbm.faces.new()
に渡される頂点の順序で決定されます。
頂点の移動
続いて、既存の頂点を操作する方法を見ていきます。
この場合、bm.verts.ensure_lookup_table()
を実行し、頂点のリストを取得しておく必要があります。その後、頂点のリストbm.verts
から、インデックスで各頂点を指定して処理を実行します。
頂点を移動したい場合は、座標vert.co
の数値を操作します。例えば、インデックス0の頂点をx軸方向に+1.0だけ移動したい場合は以下のように記述します。
bm.verts.ensure_lookup_table()
vert = bm.verts[0]
vert.co.x += 1.0
辺の削除
既存の辺を操作する場合も、事前にbm.edges.ensure_lookup_table()
を実行し、辺のリストを取得します。その後、辺のリストbm.edges
から、インデックスで各辺を指定して処理を実行します。
辺を削除したい場合は、bm.edges.remove
を実行します。例えば、インデックス0の辺を削除したい場合は以下のように記述します。
bm.edges.ensure_lookup_table()
edge = bm.edges[0]
bm.edges.remove(edge)
面の押し出し
既存の面を操作する場合も、事前にbm.faces.ensure_lookup_table()
を実行し、面のリストを取得します。その後、面のリストbm.faces
から、インデックスで各面を指定して処理を実行します。
面を押し出したい場合は、bpy.ops.mesh.extrude_region_move
を実行します。このとき、ある1つの面のみを操作したい場合は、すべての面の選択をいったん外しておく必要があります。
例えば、インデックス0の面をz方向に1.0だけ押し出したい場合は以下のように記述します。
bm.faces.ensure_lookup_table()
# すべての面の選択を外しておく
bpy.ops.mesh.select_all(action='DESELECT')
# インデックス0の面のみを選択
bm.faces[0].select = True
# 面の押し出し
bpy.ops.mesh.extrude_region_move(TRANSFORM_OT_translate={"value":(0, 0, 1.0)})
面の分割
頂点と辺、面の操作を組み合わせると、面を分割する操作も実行できます。
例えば、1つの面(四角形)の対角に存在する2つの頂点を選択して、辺を追加することで面を分割する操作は以下のように記述します。
bm.faces.ensure_lookup_table()
face = bm.faces[0]
v1 = face.verts[0]
v2 = face.verts[2]
bm.edges.new((v1, v2))
【コピペ可能】編集モードで操作するPython自動化処理の例
ここまで、Blenderの編集モードにおけるPython自動化処理の基本について解説してきました。
最後に、今回紹介した編集モードで操作するPython自動化処理の応用例を示します。ここでは、UV球のすべての面をランダムに押し出しする処理を自動化しています。
Blenderのテキストエディタに以下のスクリプトを記述します
import bpy
import bmesh
from random import uniform
# デフォルトのメッシュを削除
for mesh in bpy.data.meshes:
bpy.data.meshes.remove(mesh)
# メッシュの追加
bpy.ops.mesh.primitive_uv_sphere_add()
# 編集モードに切り替え
bpy.ops.object.mode_set(mode='EDIT')
# bmeshオブジェクトの作成
bm = bmesh.from_edit_mesh(bpy.context.object.data)
# 頂点選択モードへの切り替え
bpy.ops.mesh.select_mode(type='FACE')
# 頂点を移動
for i in range(len(bm.faces)):
# 面の選択を外しておく
bpy.ops.mesh.select_all(action='DESELECT')
# 頂点のリストを作成
bm.faces.ensure_lookup_table()
# インデックスiの面のみを選択
face = bm.faces[i]
face.select = True
# ランダムな面の押し出し
shift = uniform(-0.25, 0.25)
pos_face = face.calc_center_median()
bpy.ops.mesh.extrude_region_move(TRANSFORM_OT_translate={"value":(pos_face.x*shift, pos_face.y*shift, pos_face.z*shift)})
# オブジェクトモードに切り替え
bpy.ops.object.mode_set(mode='OBJECT')
# モディファイア「サブディビジョンサーフェス」を適用
bpy.ops.object.modifier_add(type='SUBSURF')
bpy.context.object.modifiers["細分化"].levels = 5 # English:"Subdivision"
## 以下復習 ##
# マテリアルを追加する
material_new = bpy.data.materials.new('Blue')
# 「ノードを使用」をオンにする
material_new.use_nodes = True
#「プリンシプルBSDF」のインスタンスを生成する
bsdf = material_new.node_tree.nodes["プリンシプルBSDF"] # English: "Principled BSDF"
#プリンシプルBSDFの各種パラメータを設定する
bsdf.inputs[0].default_value = (0,0,1,1) # 「ベースカラー」をランダムに設定
bsdf.inputs[6].default_value = 1 # 「メタリック」を1に設定
bsdf.inputs[9].default_value = 0 # 「粗さ」を0に設定
bsdf.inputs[17].default_value = 1 #「伝搬」を1に設定
# オブジェクトにマテリアルを追加する
bpy.context.object.data.materials.append(material_new)
上記のスクリプトを実行すると、以下の画像のように手動で作成するのは困難なオブジェクトが瞬時に生成されます。
「##以下復習##」移行の内容は以下の記事と同様の処理を実行しています。詳細を知りたい方はあわせてご覧ください。
まとめ
今回は、BlenderをPythonで自在に操作する方法について解説してきました。
「編集モード」も含めてPythonによる操作ができるようになると、Blenderの自動化処理が非常にはかどります。今回紹介したような頂点や辺、面を操作する基本的な機能からマスターし、複雑な処理もできるようになっていきましょう!
今回活用したBlender Python APIに関する日本語の情報は少ないです。もっと詳しい技術について興味のある方は、以下のようなBlender×Pythonの専門書籍を用いた学習も検討してみてください。