概要

JupyterからBlenderを使ってみたメモです。

JupyterからBlenderを使うには

記事「Jupyter NotebookからPythonのAPIでBlenderを操作する」の通りにしてできました。

以降では下記を実行しているとします。

from pathlib import Path
from subprocess import run
import bpy
from mathutils import Vector
from ipywidgets import interact

コマンドの関数を取得するには

メニューやボタンで、Ctrl + Cを押すと実行用のコードを取得できます。
あるいは、コマンドを実行すると、情報画面に実行したコードが出力されます。
これらのコードはメニューと同じ動作ですが、複数回実行する場合に効率的でないこともあります。
実際に立方体を作成して実行時間を比較してみましょう。

実行時間の比較

メニューのコード(立方体作成)

%timeit -n 5 -r 5 bpy.ops.mesh.primitive_cube_add()
>>>
1.02 ms ± 138 µs per loop (mean ± std. dev. of 5 runs, 5 loops each)

低レベルのコード(立方体作成)

%%timeit -n 5 -r 5
pts = [[-1, -1, -1], [-1, -1, 1], [-1, 1, -1], [-1, 1, 1], [1, -1, -1], [1, -1, 1], [1, 1, -1], [1, 1, 1]]
verts = [Vector(pt) for pt in pts]
faces = [[0, 1, 3, 2], [4, 5, 7, 6], [0, 1, 5, 4], [2, 3, 7, 6], [0, 2, 6, 4], [1, 3, 7, 5]]
mesh = bpy.data.meshes.new(name="Cube")
mesh.from_pydata(verts, [], faces)
obj = bpy.data.objects.new(mesh.name, mesh)
bpy.context.layer_collection.collection.objects.link(obj)
>>>
58.7 µs ± 7.88 µs per loop (mean ± std. dev. of 5 runs, 5 loops each)

低レベルのコードの方が、ややこしいですが10倍以上速いです。

関数のヘルプを見るには

通常、Jupyterでは、カーソルを関数にあるところでCtrl + Tabを押すとヘルプが見れます。しかし、Blenderの関数だと、詳しくわからないことがあります。その場合は、関数の括弧をつけずに実行すると、デフォルトの引数を確認できることがあります。

引数の書き方

Blenderの関数のいくつかは、位置引数ではなくキーワード引数にしないといけないことがあります。

インタラクティブ操作

Jupyterでは、ipywidgetsを使って、関数の引数をインタラクティブに変更できます。
以下を実行すると、プルダウンから立方体の色を変更できるようになります。

@interact
def cube_color(color={"red": (1, 0, 0), "green": (0, 1, 0), "blue": (0, 0, 1)}):
    if not (obj := bpy.data.objects.get("Cube")):
        bpy.ops.mesh.primitive_cube_add()
        obj = bpy.context.object
    if not obj.active_material:
        obj.active_material = bpy.data.materials.new("Material")
    mat = obj.active_material 
    mat.use_nodes = False
    mat.diffuse_color = color + (1,)
undefined
undefined

ちなみに、Jupyter Labだと、ipywidgetsが表示されませんでした。

複数のblendファイル

Jupyterから複数のblendファイルも扱えます。
下記は、特定のフォルダのblendファイルのオブジェクト数を出力するコードです。

%%time
for fnam in Path(特定のフォルダ).glob("*.blend"):
    bpy.ops.wm.open_mainfile(filepath=str(fnam))
    print(len(bpy.data.objects))
>>>
Wall time: 131 ms

blenderのコマンドで、同様のことができますが、時間がかかります。

%%time
cmd = "/Applications/Blender.app/Contents/MacOS/Blender"
for fnam in Path(特定のフォルダ).glob("*.blend"):
    run([cmd, "-b", fnam, "--python-expr",
         'print(len(__import__("bpy").data.objects))'])
>>>
Wall time: 2.98 s

20倍以上の時間がかかっています。

以上

广告
将在 10 秒后关闭
bannerAds