bmesh オブジェクトのインスタンス化【第 9 回 Python × Blender】
Blender においてbmesh
オブジェクトは、他のコアデータ構造に比べて非常にメモリを食い計算コストが高いものです。
効率性を維持するために、Blender ではユーザーが各種データやインスタンスの管理を API を用いてしなくてはなりません。
以下の Python スクリプトはbmesh
オブジェクトのインスタンス化の一例です、これを Blender の Text Editor にて実行してください。
import bpy import bmesh '''オブジェクトモードから始めなければなりません. scene が empty(空)であるときスクリプトは動きません.''' # オブジェクトモードに変更. bpy.ops.object.mode_set(mode='OBJECT') # 全てのオブジェクトを選択. bpy.ops.object.select_all(action='SELECT') # 選択された全てのオブジェクトを削除. bpy.ops.object.delete() '''立方体オブジェクトを作成し, 編集モードに切り替えます.''' # 半径 0.5 の立方体オブジェクトを原点に作成. bpy.ops.mesh.primitive_cube_add(radius=0.5, location=(0, 0, 0)) # 編集モードに切り替え. bpy.ops.object.mode_set(mode='EDIT') '''bmesh オブジェクトをインスタンス化する際には, bpy.data.meshes データブロックを bmesh.from_edit_mesh()の変数として渡します.''' # アクティブなオブジェクト(先ほど追加した立方体)のメッシュデータブロックへの参照を記憶. mesh_datablock = bpy.context.object.data # 操作する bmesh オブジェクト(bm と名付ける)を作成. bm = bmesh.from_edit_mesh(mesh_datablock) # bmesh オブジェクトを print. print(bm)
ターミナルには以下のような結果が出ています。頂点(vertex)・辺(edge)・面(face)がそれぞれ 8・12・6 であるということもなんとなくわかりますね。
<BMesh(0x109acf008), totvert=8, totedge=12, totface=6, totloop=24>
上記の Python スクリプトを見てもわかると思いますが、bmesh
オブジェクトをインスタンス化する際には、bpy.data.meshes
データブロックをbmesh.from_edit_mesh()
の変数として渡します。
一方、上記のコマンドを Interactive Console で実行してもbmesh
オブジェクトをインスタンス化することはできません。
Blender ではあるbmesh
オブジェクトがアクティブに用いられていると検知できないと、そのbmesh
オブジェクトのbpy.data.meshes
データブロックへの参照をガベージコレクタが消してしまいます。
その結果 Interactive Console での実行結果は、
<BMesh dead at some_memory_address>
となってしまい、bmesh
オブジェクトのインスタンス化に失敗することになります。
bmesh
オブジェクトが空間計算量と時間計算量共に食ってしまうのでこれらの挙動は必要な挙動であるので、bmesh
オブジェクトをインスタンスとして保持するにはこのように余分なコマンドを実行する必要があるのです。