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オブジェクトをインスタンスとして保持するにはこのように余分なコマンドを実行する必要があるのです。