基本的なメッシュ変形【第 11 回 Python × Blender】

前回 Blender の 3D オブジェクトのメッシュ(頂点・辺・面)の選択方法について書きました。
tamaki-py.hatenablog.com



今回はその選択したメッシュに対し基本的な変換(移動・回転など)を施してみたいと思います。



実は、第 7 回で説明したオブジェクトの変換に用いるbpy.ops.transformクラスの関数が、メッシュの変換に対してそのまま用いることができます。
tamaki-py.hatenablog.com



以下の Python サンプルスクリプトは 3 回立方体オブジェクトを作成し、

  • 1 回目はある面をbpy.ops.transform.rotate()で回転
  • 2 回目はある辺をbpy.ops.transform.translate()で移動
  • 3 回目はある頂点をbpy.ops.transform.translate()で移動

してみた結果となっています。

続きを読む

3D オブジェクトの頂点・辺・面の選択【第 10 回 Python × Blender】

bmeshオブジェクトから頂点(vertex)・辺(edge)・面(face)のいくつかを個別に選択するにはBMesh.verts, BMesh.edges, BMesh.facesのブール値を変更します。



以下は正十二面体オブジェクトを定義して配置し、そのうちいくつかの頂点・辺・面を選択する Python サンプルスクリプトです。

続きを読む

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

編集モード【第 8 回 Python × Blender】

これまでの第 1~7 回の記事でお話ししてきた Blender のモードはオブジェクトモード(Object Mode)と呼ばれるものです。



このモードでは一つないしは複数のオブジェクトを作ったり、選択して(同時に)操作することができます。例えば複数のオブジェクトを移動したり、回転させたり、拡大・縮小することができました。



これらの操作は基本的に BlenderPython API の一つであるbpyモジュールによって行われていました。



そして、このオブジェクトモードは Blender のデフォルトのモードとなっています。



対して一つのオブジェクトの一つないしは複数の頂点を操作し、より詳細な変形を行うモードが編集モード(Edit Mode)で、このモードでは Blender の 3D アートのツールとしての側面が輝きだします。



そしてこの編集モードにおける操作のほとんどを取り仕切るのが BlenderPython API の一つであるbmeshモジュールです。
docs.blender.org




これまでに学んできたオブジェクトモードで用いられるbpyモジュールと、これから学ぶ編集モードで用いられるbmeshモジュールの機能を用いれば、どんな 3D の形状も作れるようになります。



今回の記事はこのbmeshモジュールの解説に入る前に、オブジェクトモードと編集モードの切り替え方と注意点、 2 つのモードのPython スクリプトによる切り替え方を解説することです。

続きを読む

bpy.ops.transform による変換【第 7 回 Python × Blender】

今回はbpy.ops.transformによる変換についての記事です。



まずは以下のut.pyという Python スクリプトBlender で実行してみてください。このスクリプトif __name__ == "__main__"以下の部分はbpy.ops.transformを説明するためのスクリプト例です。

続きを読む