Blender Python tutorial
参考サイトはこちらです。
Index(目次)
- よく使用される単語: 単語の表があります。
- クイックスタート: BlenderでのPythonスクリプト実行の準備とBMeshについて
- 円を作成する: Pythonコードと細かいPythonコマンドの説明
- Pythonでの描画サンプルコード
- ベストプラクティスで学習する
- Blender Python APモジュール
よく使用される単語
単語 | 内容 |
---|---|
メッシュ | Blenderでは、Vertex(点)、Edge(辺)、Face(面)で構成された3DオブジェクトのことをMesh(メッシュ)と呼びます。 . |
ジオメトリ | シェーディングポイントに関する幾何学的情報 |
ディゾルブ | ディゾルブは、ジオメトリを削除し、周辺のジオメトリで埋めます。ジオメトリを削除するとできてしまう穴を、もう一度埋める作業の代わりに使用できます。 |
Pythonコマンド一覧
コマンド、内容、パラメータの順に記載していますが、パラメータは実際に入力する例として値が入っています。もちろんそのまま使用できます。
プリミティブの作成コマンド
No | コマンド | 内容 | パラメータ(引数) |
---|---|---|---|
1 | bpy.ops.mesh.primitive_circle_add | 円メッシュを作成する | 頂点= 32、半径= 1.0、fill_type = 'NOTHING' 、calc_uvs =真、enter_editmode =偽、ALIGN = 'WORLD' 、位置= (0.0、 0.0、 0.0) 、回転= (0.0、 0.0、 0.0) 、スケール= (0.0、 0.0、 0.0) ) |
2 | bpy.ops.mesh.primitive_cone_add | 円錐メッシュを作成します | 頂点= 32、radius1を= 1.0、radius2 = 0.0、深さ= 2.0、end_fill_type = 'Ngonの'、calc_uvs =真、enter_editmode =偽、ALIGN = 'WORLD' 、位置= (0.0、 0.0、 0.0) 、回転= ( 0.0、 0.0、 0.0) 、規模= (0.0、 0.0、 0.0) |
3 | bpy.ops.mesh.primitive_cube_add | 立方体メッシュを作成します | サイズ= 2.0、calc_uvs =真、enter_editmode =偽、ALIGN = 'WORLD' 、位置= (0.0、 0.0、 0.0) 、回転= (0.0、 0.0、 0.0) 、規模= (0.0、 0.0、 0.0) |
4 | bpy.ops.mesh.primitive_cube_add_gizmo | 立方体メッシュを作成します | calc_uvs =真、enter_editmode =偽、ALIGN = 'WORLD' 、位置= (0.0、 0.0、 0.0) 、回転= (0.0、 0.0、 0.0) 、規模= (0.0、 0.0、 0.0) 、マトリックス= ((0.0 、 0.0、 0.0、 0.0)、 (0.0、 0.0、 0.0、 0.0)、 (0.0、 0.0、 0.0、 0.0)、 (0.0、 0.0、 0.0、 0.0) |
5 | bpy.ops.mesh.primitive_cylinder_add | 円柱メッシュを作成します | 頂点= 32、半径= 1.0、深さ= 2.0、end_fill_type = 'Ngonの'、calc_uvs =真、enter_editmode =偽、ALIGN = 'WORLD' 、位置= (0.0、 0.0、 0.0) 、回転= (0.0、 0.0、 0.0) 、規模= (0.0、 0.0、 0.0) |
6 | bpy.ops.mesh.primitive_grid_add | グリッドメッシュを作成する | x_subdivisions = 10、y_subdivisions = 10、サイズ= 2.0、calc_uvs =真、enter_editmode =偽、ALIGN = 'WORLD' 、位置= (0.0、 0.0、 0.0) 、回転= (0.0、 0.0、 0.0) 、規模= ( 0.0、 0.0、 0.0) |
7 | bpy.ops.mesh.primitive_ico_sphere_add | Icosphereメッシュを作成します | 細分= 2、半径= 1.0、calc_uvs =真、enter_editmode =偽、ALIGN = 'WORLD' 、位置= (0.0、 0.0、 0.0) 、回転= (0.0、 0.0、 0.0) 、規模= (0.0、 0.0、 0.0) |
8 | bpy.ops.mesh.primitive_monkey_add | スザンヌメッシュを構築する | サイズ= 2.0、calc_uvs =真、enter_editmode =偽、ALIGN = 'WORLD' 、位置= (0.0、 0.0、 0.0) 、回転= (0.0、 0.0、 0.0) 、規模= (0.0、 0.0、 0.0) |
9 | bpy.ops.mesh.primitive_plane_add | 4つの頂点を持つ塗りつぶされた平面メッシュを作成します | サイズ= 2.0、calc_uvs =真、enter_editmode =偽、ALIGN = 'WORLD' 、位置= (0.0、 0.0、 0.0) 、回転= (0.0、 0.0、 0.0) 、規模= (0.0、 0.0、 0.0) |
10 | bpy.ops.mesh.primitive_torus_add | トーラスメッシュを作成します | ALIGN = 'WORLD' 、位置= (0.0、 0.0、 0.0) 、回転= (0.0、 0.0、 0.0) 、major_segments = 48、minor_segments = 12、モード= 'MAJOR_MINOR' 、major_radius = 1.0、minor_radius = 0.25、abso_major_rad = 1.25、abso_minor_rad = 0.75、generate_uvs = True |
11 | bpy.ops.mesh.primitive_uv_sphere_add | UV球メッシュを作成します | セグメント= 32、ring_count = 16、半径= 1.0、calc_uvs =真、enter_editmode =偽、ALIGN = 'WORLD' 、位置= (0.0、 0.0、 0.0) 、回転= (0.0、 0.0、 0.0) 、規模= ( 0.0、 0.0、 0.0) |
クイックスタート
下のような記載がありました。(日本語に翻訳)
【Blender Python APIの機能】
・ ユーザーインターフェイスで可能なデータ(シーン、メッシュ、パーティクルなど)を編集します。
・ユーザー設定、キーマップ、およびテーマを変更します。
・独自の設定でツールを実行します。
・メニュー、ヘッダー、パネルなどのユーザーインターフェイス要素を作成します。
・新しいツールを作成します。
・インタラクティブなツールを作成します。
・Blenderと統合する新しいレンダリングエンジンを作成します。
・データとそのプロパティへの変更をサブスクライブします。
・既存のBlenderデータに新しい設定を定義します。
・Pythonを使用して3Dビューポートで描画します。
始める前にやっておくと良いこと
Blender2.69使用
【設定画面を開く】
FIle -> User Preference
DeveloperExtra とPythonのツールチップを有効にします。
- DeveloperExtra -> Blender2.69(mac版)には見つかりませんでした。。。
- PythonTooltipsにチェックを入れる(デフォルトでチェックが入ってました)
Blender2.93使用
【スプラッシュ画面を開く】
※自動で表示されます。
ここで、言語の設定ができます。「言語」をJapaneseに変更します。
そのほか、マウスのコントロールなど変更可能です。
【設定画面を開く】
インターフェース -> 表示 -> Pythonツールチップを表示
Pythonコンソールを使用する
上のキャプチャのように「default」から「Scripting」に変更します。
システムコンソールを表示する
しかしこのままだと、システムコンソールには日本語が文字ばけします。
なので、以下のようにBlenderを起動します。
Blender2.93使用
こちらも同様です。※クリックする場所が違うけど。。。
これで、pythonコードをテストするのにとても便利です。
そして、参考サイトの下の方に行くと、サンプルコードがあるので実行してみると動きがわかります。
それで物足りなければ、参考サイトの下のような部分を参照してみると良いです。
システムコンソールを開く
サンプルコード
- Blender Python API
- 操作オペレーションとコード(bpy.ops)
- オブジェクトの削除: bpy.ops.object.delete()
- Cubeの作成: bpy.ops.mesh.primitive_cube_add(location=(0,0,0))
「(0,0,0)」の部分には座標が入ります。上記のは画面の中心にできます。 - オブジェクト選択: bpy.context.selected_objects ※配列になっている
- 編集モードに変換: bpy.ops.object.mode_set(mode='EDIT')
オブジェクトモード: bpy.ops.object.mode_set(mode='OBJECT') - モードの変換: bpy.ops.object.editmode_toggle(): 引数なし、編集モードとオブジェクトモードを切り替える
BMeshを使うサンプルコード
参考ページはこちらです。
bpy.bmeshモジュールは、blenderのbmeshデータへのアクセスを提供します。
BMeshとは
ジオメトリ接続データを備えたBlenderの内部メッシュ編集APIへのアクセスと、分割、分離、折りたたみ、
ディゾルブなどの編集操作へのアクセスを提供します。公開されている機能はCAPIに厳密に従っており、Blender独自のメッシュ編集ツールで使用される関数にPythonがアクセスできるようにします。
早い話が、「メッシュ」を操作するということです。
次はサンプルコードを実行してみましょう。
<サンプルコード>※参考ページにあったものです。
# This example assumes we have a mesh object selected
import bpy
import bmesh
# Get the active mesh
me = bpy.context.object.data
# Get a BMesh representation
bm = bmesh.new() # create an empty BMesh
bm.from_mesh(me) # fill it in from a Mesh
# Modify the BMesh, can do anything here...
for v in bm.verts:
v.co.x += 1.0
# Finish up, write the bmesh back to the mesh
bm.to_mesh(me)
bm.free() # free and prevent further access
Script画面を開いた状態で、下のように「新規」をクリックします。
そしたら、文字が入力できるようになるので、サンプルコードをコピペして貼り付けてみましょう。
※「コピペ」=文字を選択して「Ctrl + C」(コピー)してから「Ctrl + V」(ペースト)すること
貼り付けたら、右側にある「▶」ボタンを押してプログラムを実行します。
すると、初期表示していたCubeがX軸方向に移動します。
ちなみに、エラーメッセージなどを見るとプログラムの修正も楽です。
なので、ヘッダーメニューにある「ウィンドウ」->「システムコンソール切り替え」をクリックしてやるとよいです。
- bmesh.types.BMesh.from_mesh: 既存のメッシュデータブロックからこのbmeshを初期化します。
[from_mesh(メッシュ、face_normals = True、use_shape_key = False、shape_key_index = 0)]- パラメーター
- mesh(Mesh)–ロードするメッシュデータ。
- use_shape_key(boolean)–シェイプキーの場所を使用します。
- shape_key_index(int)–使用するシェイプキーインデックス。
bm = bmesh.new() # 空のBMeshを作成する
bm.from_mesh(me) # 現在の編集モードから初期化する
- bmesh.from_edit_mesh:
me = bpy.context.object.data bpy.ops.object.mode_set(mode='EDIT') # エディットモードに変更 bm = bmesh.from_edit_mesh(me)
このような形で、BMeshを取得します。そして、いろいろなコントロールを行うというわけです。
円を作成する
プログラム的には下のように処理を行うと作成することができました。
- データを書き込むためにプリミティブ(Cube)を作成
- BMeshを作成
- 円の作成(BMesh)
- 作成したBMeshをデータに書き込む -> これで画面上に表示される
- 作成したときにプリミティブの名前「Cube(立方体)」を変更
import bpy
import bmesh
import math
import mathutils
# 1. 立方体を作成
bpy.ops.mesh.primitive_cube_add(location=(0,0,0))
# 存在するオブジェクトのデータを取得
me = bpy.context.object.data
# 2. BMeshの作成
bm = bmesh.new()
# 3. 円の作成(BMesh)
# Add a circle XXX, should return all geometry created, not just verts.
bmesh.ops.create_circle(
bm,
cap_ends=False,
radius=1.0,
segments=8)
# 4. 作成したBMeshをデータに書き込む
bm.to_mesh(me)
bm.free()
# 5. 作成したときにプリミティブの名前「Cube(立方体)」を変更
for obj in bpy.data.objects:
print(obj.name)
if obj.name == 'Cube':
print('change')
obj.name = 'Test'
Pythonでの描画サンプルコード
ベジェ曲線のサンプルコード
. ペジェ曲線(Bezer Curv)を描く:
ops.curve.primitive_bezier_circle_add(radius=1.0,
location=(0.0, 0.0, 0.0),
enter_editmode=True)
from bpy import context, data, ops
# Create a bezier circle and enter edit mode.
ops.curve.primitive_bezier_circle_add(radius=1.0,
location=(0.0, 0.0, 0.0),
enter_editmode=True)
# Subdivide the curve by a number of cuts, giving the
# random vertex function more points to work with.
ops.curve.subdivide(number_cuts=16)
# Randomize the vertices of the bezier circle.
# offset [-inf .. inf], uniform [0.0 .. 1.0],
# normal [0.0 .. 1.0], RNG seed [0 .. 10000].
ops.transform.vertex_random(offset=1.0, uniform=0.1, normal=0.0, seed=0)
# Scale the curve while in edit mode.
ops.transform.resize(value=(2.0, 2.0, 3.0))
# Return to object mode.
ops.object.mode_set(mode='OBJECT')
オブジェクトの名前など一式
プログラムで、オブジェクトをコントロールするのに「名前」がわからないととても不便です。
なので、それを一覧化します。
- Structure
- Vertex: 点
- Edge: 辺
- Face: 面
- Normals: 法線=何かに垂直な方向または線であり、通常は三角形またはサーフェスですが、線、曲線上の点の接線、または表面上の点の接平面を基準にすることもできます
ベストプラクティスで学習する
こちらにベストプラクティスのページがあります。
Blender Pythonはコードスタイルとして、PEP8を採用している。
大まかには下のようなところを気をつけましょう、というところでした。
- クラス名のキャメルキャップ:MyClass
- すべて小文字の下線で区切られたモジュール名:my_module
- 4つのスペースのインデント(タブなし)
- 演算子の周りのスペース:、ではありません ◯「1 + 1」 X「1+1」
- 明示的なインポートのみを使用します(ワイルドカードのインポートは使用しません*)
- 1行で複数のステートメントを使用しないでください:、代わりに2行に分けてください。if val: body
- 列挙型には一重引用符を使用し、文字列には二重引用符を使用します。
- リストのコピーを避ける: 「新しいリストを返すよりも関数にリストを変更させる方が高速です。」
Blender Python APモジュール
コンテキストアクセス(bpy.context)
- bpy.context.area
- bpy.context.blend_data
- bpy.types.BlendData、(読み取り専用)
- bpy.context.collection
- bpy.types.Collection、(読み取り専用)
- bpy.context.engine
- bpy.context.gizmo_group
- bpy.types.GizmoGroup、(読み取り専用)
- bpy.context.layer_collection
- bpy.types.LayerCollection、(読み取り専用)
- bpy.context.mode
タイプ
['EDIT_MESH'、 'EDIT_CURVE'、 'EDIT_SURFACE'、 'EDIT_TEXT'、 'EDIT_ARMATURE'、 'EDIT_METABALL'、 'EDIT_LATTICE'、 'POSE'、 'SCULPT'、 'PAINT_WEIGHT'、 'PAINT_VERTEX'、 'PAINT_TEXTURE'の列挙型、 'PARTICLE'、 'OBJECT'、 'PAINT_GPENCIL'、 'EDIT_GPENCIL'、 'SCULPT_GPENCIL'、 'WEIGHT_GPENCIL'、 'VERTEX_GPENCIL']、デフォルト 'EDIT_MESH'、(読み取り専用) - bpy.context.preferences
- bpy.types.Preferences、(読み取り専用)
- bpy.context.region
- bpy.types.Region、(読み取り専用)
- bpy.context.region_data
- bpy.types.RegionView3D、(読み取り専用)
- bpy.context.scene
- bpy.types.Scene、(読み取り専用)
- bpy.context.screen
- bpy.types.Screen、(読み取り専用)
- bpy.context.space_data
- bpy.types.Space、(読み取り専用)
- bpy.context.tool_settings
- bpy.types.ToolSettings、(読み取り専用)
- bpy.context.view_layer
- bpy.types.ViewLayer、(読み取り専用)
- bpy.context.window
- bpy.types.Window、(読み取り専用)
- bpy.context.window_manager
- bpy.types.WindowManager、(読み取り専用)
- bpy.context.workspace
- bpy.types.WorkSpace、(読み取り専用)
データアクセス(bpy.data)
Blenderの内部データへのアクセス、これはサンプルコードを参考にするようです。
import bpy
# print all objects
for obj in bpy.data.objects:
print(obj.name)
# print all scene names in a list
print(bpy.data.scenes.keys())
# remove mesh Cube
if "Cube" in bpy.data.meshes:
mesh = bpy.data.meshes["Cube"]
print("removing mesh", mesh)
bpy.data.meshes.remove(mesh)
# write images into a file next to the blend
import os
with open(os.path.splitext(bpy.data.filepath)[0] + ".txt", 'w') as fs:
for image in bpy.data.images:
fs.write("%s %d x %d\n" % (image.filepath, image.size[0], image.size[1]))
メッセージバス(bpy.msgbus)
BlenderデータブロックのプロパティがデータAPIを介して変更されたときに通知を受信できます。
詰まる所は、bpy.dataのオブジェクトに変更があった時、その変更されたことを受信(知ること)ができるということです。
<サンプルコード>※上記のリンク先にコードがあります。
アクティブオブジェクトの場所の変更に対するサブスクリプションの例
import bpy
# Any Python object can act as the subscription's owner.
owner = object()
subscribe_to = bpy.context.object.location
def msgbus_callback(*args):
# This will print:
# Something changed! (1, 2, 3)
print("Something changed!", args)
bpy.msgbus.subscribe_rna(
key=subscribe_to,
owner=owner,
args=(1, 2, 3),
notify=msgbus_callback,
)
鍵になるのは下のコードです。
bpy.msgbus.subscribe_rna(キー、所有者、引数、通知、オプション= set())
パラメーター:
- キー(マルチプル)–サブスクライブされているデータのタイプを表します
- 所有者(任意のタイプ。)–このサブスクリプションのハンドル(IDで比較)。
- オプション(文字列のセット)–
サブスクライバーの動作を変更します。
PERSISTENT 設定すると、IDデータを再マッピングするときにサブスクライバーが保持されます。
演算子(bpy.ops)
「演算子」と翻訳されているが、オペレーター(操作オブジェクト)と解釈した方がしっくりくるかもしれない。。。
大まかな機能としては、以下のものがあるようです。
- 演算子の呼び出し:呼び出し元の演算子へのPythonアクセスを提供します。
{'RUNNING_MODAL', 'CANCELLED', 'FINISHED', 'PASS_THROUGH'}{'FINISHED'}{'CANCELLED'} のみ使用可能 - キーワードと位置引数: APIドキュメントにある順番で引数を渡す必要がある
bpy.ops.test.operator(override_context, execution_context, undo) 1: override_context 2: execution_context 3: undo - コンテキストのオーバーライド(以下サンプルコード)
# remove all objects in scene rather than the selected ones import bpy override = bpy.context.copy() override['selected_objects'] = list(bpy.context.scene.objects) bpy.ops.object.delete(override)
サブモジュール
現状はここまでです。
でわでわ。。。