はじめに
blenderにはpythonが内蔵されており、ほとんどの内部コマンドを制御できます。GUIのコンソールからも呼べますしスクリプトファイルを作っておいて実行することもできます。
あくまで主体がblenderなので、渡されたスクリプトをblender内蔵の python で実行するわけです。--backgroundオプションを渡すとGUIも起動しないので、あたかもpythonスクリプトをCUIで実行するような挙動になります。
blender --background --python hogehoge.py
OSXの場合はblender.appの--argsオプションで引数を渡せばいけるようですね。
open -a blender.app --args --background --python hogehoge.py
これでblenderのpythonによる自動化は十分なのですが、逆に、pythonを主体にblenderを外部モジュールとして呼ぶこともできます。
そんなblenderのpythonモジュールのビルド方法はこちらに書いてあります。ビルド過程は退屈なのであとで説明します。まずは使ってみましょう。
レンダリングしてみる
blenderでは起動時にデフォルトで四角い箱、光源、カメラが作成されるので、起動状態でのレンダリング結果を取得してみましょう。
import bpy
bpy.ops.render.render()
bpy.data.images['Render Result'].save_render(filepath = '/tmp/image.png')
のようなhogehoge.pyを用意して、
$ python3 ./hogehoge.py
で/tmp/image.pngが生成されました。
もちろん、冒頭に説明したようにblenderにhogehoge.pyを渡せば同じことができます。
Jupyter notebook上で blender
さて、python側の土俵に持ち込んだわけなので、jupyter notebook上とかでも使えることになりますね。となるとレンダリング結果をpythonの配列として取り出してimshowしたいところです。しかし、ちょっと調べた限りでは、どうもファイルを介さずにレンダリング結果を直接取ってくる方法が無いようです。こちらの方法がいい感じですが、残念ながらblenderのGUIがない状態では機能しませんでした。やむを得ないのでtempfileを介して取ることにしますが、だいぶ負けなかんじですね。
def get_img(size=[480,640]):
scene = bpy.context.scene
scene.render.resolution_x = size[1]
scene.render.resolution_y = size[0]
scene.render.resolution_percentage = 100
tmpdir=tempfile.TemporaryDirectory()
scene.render.filepath=tmpdir.name+"/hoge"
bpy.ops.render.render(write_still=True)
img=Image.open(tmpdir.name+"/hoge.png")
tmpdir.cleanup()
return img
まあともあれ、これを使えば下記のようにJupyter notebook上でレンダリング結果を眺められます。ちょっとずつ移動させながらプロットしてみました。jupyter notebookはこちらで見れます。
使ってみたまとめ
以上のように、python 側からblenderを呼び出すことができました。
しかし、冒頭のようにblenerからpythonを呼ぶのに比べてどういう場合に便利なのでしょう。一つは外部ライブラリとの連携ですが、blender側のpythonでパスを設定するだけな気がします。jupyterで使うのも楽しいですが、ググると他にも方法がありそうです。
結局のところ気分の問題にすぎないのかもしれません。ファイルを介さずに画像のやりとりが出来なかったのはだいぶ痛いです。まあ、使っていて楽しければそれで勝利な気もしますが。
ほんとうは機械学習との組み合わせまでやってみたかったのですが、環境構築で力尽きたので今回のエントリはここまでとします。
これ以降はビルド編です。
ビルドについて
基本的には公式に従えばよいのですが、いくつか罠がありましたので記録を残しておきます。下記はOSX El Capitanで行いました。
ビルド準備
python3で、かつフレームワーク形式でないといけないそうですので、homebrewのpython3を使います。
brew install python3
blenderのソースを落とします。古いソースだとcmakeがOSや開発環境のバージョンに追従できていなかったりするので、最新ソースでいきます(それはそれで地雷があるかもしれませんが)。
blender_dev
+-- blender (gitから)
+-- lib (svnから)
+-- build (ビルド用)
のようなフォルダ構成で作業します。libがないとビルドは通りません(ハマりポイント1:後述)。
mkdir blender_dev
cd blender_dev
git clone git://git.blender.org/blender.git
cd blender
git submodule update --init --recursive
git submodule foreach git checkout master
git submodule foreach git pull --rebase origin master
cd ..
mkdir lib
cd lib
svn checkout https://svn.blender.org/svnroot/bf-blender/trunk/lib/darwin-9.x.universal
cd ..
mkdir build
blender/build_files/cmake/platform/platform_apple.cmake
の96行目と210行目で、デフォルトのフレームワークパスが使われているので、brewのpython3のパスを指定します(ハマりポイント2)。
#-- line 96 ---
# set(_py_framework "/Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}")
set(_py_framework "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/")
...
#-- line 210 ---
# set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /Library/Frameworks/Python.framework/Versions/${PYTHON_VERSION}/Python")
set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} /usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/Python")
ビルド&インストール
さて、やっとビルドです。
cd build
cmake \
-D WITH_PYTHON_INSTALL=OFF \
-D WITH_PLAYER=OFF \
-D WITH_PYTHON_MODULE=ON \
../blender/
make
make install
make installの実行先はbin以下になっていて、2.78というフォルダに必要なモジュールをコピーするようです。その後、bpy.soと2.78フォルダをsite-packagesにコピーすれば動くとドキュメントには書いてありますが、2.78というフォルダ名ではなくreleaseというフォルダ名でないと動きませんでした(ハマりポイント3:後述)。
dest=/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages
cp ./bin/bpy.so ${dest}
cp -R ./bin/2.78 ${dest}
ln -s ${dest}/2.78 ${dest}/release
これでpython3からimport bpyができるようになります。
### ハマりポイント1
lib以下を作っていないと下記のように怒られました。
CMake Error at build_files/cmake/platform/platform_apple.cmake:36 (message):
Mac OSX requires pre-compiled libs at:
'/Users/***/git/blender/../lib/darwin-9.x.universal'
公式ドキュメントに書いてますが、プリコンパイルされた依存ライブラリを使えとのことです。まあこれはハマりポイントというよりは公式をちゃんと読めということで。
### ハマりポイント3
python3からimport bpyすると、下記のように怒られて落ちます。2.78/*へのパスが見つからないようで、ググっても「ちゃんとコピーした?」みたいな回答が大量に見つかります。しましたよ、でもだめなんです。
BLT_lang_init: 'locale' data path for translations not found, continuing
bpy: couldnt find 'scripts/modules', blender probably wont start.
Freestyle: couldn't find 'scripts/freestyle/modules', Freestyle won't work properly.
ImportError: No module named 'bpy_types'
ImportError: No module named 'bpy_types'
pyrna_srna_ExternalType: failed to find 'bpy_types' module
ImportError: No module named 'bpy_types'
ImportError: No module named 'bpy_types'
pyrna_srna_ExternalType: failed to find 'bpy_types' module
ImportError: No module named 'bpy_types'
pyrna_srna_ExternalType: failed to find 'bpy_types' module
F1016 18:22:03.065414 2006614016 utilities.cc:322] Check failed: !IsGoogleLoggingInitialized() You called InitGoogleLogging() twice!
ドキュメントには2.78というフォルダをコピーしろと書いているのですが、さらに、2.78というフォルダをreleaseというフォルダ名でアクセスできるようにしないとだめでした。