概要
- Blender Python APIを使って2つのstlファイルのブーリアン演算をバッチ処理するよ
- stlを読み込んだ後はbpy.data.objectsを使って該当のオブジェクトを呼び出すよ
- ブーリアン処理はmodifierを使うよ
Blender Python API is 何?
Blenderという3Dモデリングソフトウェア上で出来ることの大半をPythonで実行するためのAPIです。ここではWindows上でバージョン2.93.5を使用します。
- 公式
- API Documentation
-
Blender 2.93.5 Release Candidate Python API Documentation — Blender Python API
- これを読んでるときは2.93.5のリファレンスじゃないかも
-
Blender 2.93.5 Release Candidate Python API Documentation — Blender Python API
前提
**「foo.stlとbar.stlがあって、2つのstlを結合してunion.stlを作りたいよ!」**という前提で作業します。
ファイルの初期構成は下記の様になってると思ってください
./
├ bar.stl
├ foo.stl
└ union.py
実行後は
./
├ bar.stl
├ foo.stl
├ union.py
└ union.stl
のようになります。
ソースコード
import bpy # blenderモジュール
from os import path
# 既存のオブジェクトをすべて削除
for obj in bpy.data.objects:
obj.select_set(True)
bpy.ops.object.delete()
# fooとbarのstl読込
CURRENT_PATH = path.dirname(path.abspath(__file__)) + "\\"
bpy.ops.import_mesh.stl(filepath=CURRENT_PATH + 'foo.stl')
bpy.ops.import_mesh.stl(filepath=CURRENT_PATH + 'bar.stl')
# fooとbarのオブジェクト呼び出し
foo_index = bpy.data.objects.find('foo')
foo_object = bpy.data.objects[foo_index]
bar_index = bpy.data.objects.find('bar')
bar_object = bpy.data.objects[bar_index]
# fooにbarを結合する
modifier = foo_object.modifiers.new(type='BOOLEAN', name='union')
modifier.object = bar_object
modifier.operation = 'UNION'
# 結合したfooを書き出す
foo_object.select_set(True)
bar_object.select_set(False)
bpy.ops.export_mesh.stl(filepath=CURRENT_PATH+'union.stl', use_selection=True)
実行方法
blender.exeに--backgroundと--pythonオプションをつけて最後にスクリプト名を指定して実行します。
デフォルトの場所にインストールしたのであれば下記の様な.batファイルを作ると実行が楽になります。
"C:\Program Files\Blender Foundation\Blender 2.93\blender.exe" --background --python union.py
実際にスクリプトを書く時のTIPS
インポートできるファイルの種類
Blender上のインポートメニューにあるように、import_meshでは.ply、.stlが、import_sceneでは.fbx、.gltf、.obj、x3dが読み込めるようです。
オブジェクトの存在確認
スクリプトを組んだ時、命名規則に沿ってつけたファイル名でループを回したり、もしかすると抜けがある前提があったりしたときに実際にそのファイルが存在するか、あるいは読み込まれたかどうかが分からない場合があるときに使用します。
# ファイルの存在確認
if os.path.isfile(filepath):
print(`OK`)
else:
print(`NG`)
# オブジェクトが読み込まれているかどうかの確認
foo_index = bpy.data.objects.find('foo')
foo_object = None
if 0 <= foo_index: # indexが0以上なら存在する
foo_object = bpy.data.objects[foo_index]
- 参考
新規に空オブジェクトを作ってそっちに結合したい
これは少し複雑です。
mesh = bpy.data.meshes.new(name='union')
union_object = bpy.data.objects.new('union', object_data=mesh)
view_layer = bpy.context.view_layer
view_layer.active_layer_collection.collection.objects.link(union_object)
modifier = union_object.modifiers.new(type='BOOLEAN', name='union1')
modifier.object = foo_object
modifier.operation = 'UNION'
modifier = union_object.modifiers.new(type='BOOLEAN', name='union2')
modifier.object = bar_object
modifier.operation = 'UNION'
bpy.data.object.newで新規にオブジェクトを作るだけではだめで、事前にmeshを作って渡さないといけなかったり、view_layerに登録する必要があったりして知らないと大変です。
ブール演算の種類
Blender上でもあるように交差(INTERSECT)、結合(UNION)、差分(DIFFERENCE)の3つの操作があります。modifier.operatorに渡す引数で操作を変更できます。
結合した後に滑らかにしたい(Subdivision Surface)
ここでは説明しませんがSubdivision Surfaceを使うとメッシュを滑らかにできます。
modifier.newのパラメータでtype='SUBSURF'を指定してください。
続きの作業をBlenderで行いたい
現在のシーンを保存するbpy.ops.wm.save_as_mainfileメソッドがあります。
bpy.ops.wm.save_as_mainfile(CURRENT_PATH + 'export.blend')
既に同じ名前のファイルがある場合は、古いファイルがexport.blend1のような形で残ります。
まとめ
ブーリアン演算を自力で実装するのは結構大変だと思います。
外部ツールとしてBlenderを使うことで楽になることもあるのではないかと思います。