松本市のコワーキングスペースKNOWERSで月に1回、「Pythonもくもく会」を開催していて、僕はBlenderとPythonを組み合わせて遊んでいます。
今回はもくもく会で作った物理シミュレーションをお見せします。
動作環境
- macOS High Sierra 10.13.2
- Blender 2.79
bash_profileの設定
BlenderにはPythonが組み込まれており、「Cubeを作る」や「Cubeの名前を取得」などがコードを通じて操作できます。
組んだPythonプログラムはTerminalかBlender内のコンソールから実行できます。Terminalからの実行を楽にやるために、bash_profileにaliasを追加しておくといいです。
$ alias blender='/Applications/blender/blender.app/contents/MacOS/blender' $ source .bash_profile
すると、Terminalで「blender」と打つだけで起動できるようになります。
$ blender --python hogehoge.py $ blender --background --python hogehoge.py (バックグラウンドレンダリング)
物理シミュレーション
さて、本題の物理シミュレーション。参考にさせてもらったサイトはこちら。
参考:Blenderの物理シミュレーションをpythonスクリプトで作成 – 株式会社CFlatの明後日スタイルのブログ
これをベースにプログラムを組みました。
ソースコード
import bpy import os import math def delete_all(): """ デフォルトで存在しているCubeを削除 """ bpy.ops.object.delete() def create_scene(): """ シーンを作成 """ # Cube作成 cube_count = 10 for axis_x in range(0, cube_count): for axis_y in range(0, cube_count): for axis_z in range(0, cube_count): # pattern1 bpy.ops.mesh.primitive_cube_add(location=(axis_x*2, axis_y*2, axis_z*2)) bpy.ops.rigidbody.object_add() # pattern2 # bpy.ops.mesh.primitive_cube_add(location=(axis_x*2, axis_y*2, axis_z*2), rotation=(15, 15, 0)) # bpy.ops.rigidbody.object_add() # pattern3 # bpy.ops.mesh.primitive_cube_add(location=(axis_x*2, axis_y*2, axis_z*2)) #bpy.ops.rigidbody.object_add() # bpy.ops.object.modifier_add(type='SOFT_BODY') # 平面作成 bpy.ops.mesh.primitive_plane_add(location=(cube_count-1, cube_count-1, -10)) bpy.ops.rigidbody.object_add(type='PASSIVE') bpy.data.objects["Plane"].scale = (cube_count+10, cube_count+10, 1) # カメラ bpy.data.objects["Camera"].location = (cube_count+20, cube_count+20, cube_count+20) bpy.data.objects["Camera"].rotation_euler = (math.pi/6, 0, math.pi*3/4) bpy.data.cameras["Camera"].lens = 10 # 照明 bpy.data.objects["Lamp"].location = (0, 0, cube_count+10) bpy.data.lamps["Lamp"].type = 'SUN' def start_simulation(): """ 物理シミュレーション """ bpy.ops.ptcache.bake_all() # 動画作成 bpy.context.scene.render.resolution_x = 400 bpy.context.scene.render.resolution_y = 300 bpy.context.scene.render.resolution_percentage = 100 bpy.context.scene.render.image_settings.file_format = 'AVI_JPEG' bpy.data.scenes["Scene"].render.filepath = "Physical.avi" bpy.context.scene.frame_start = 0 bpy.context.scene.frame_end = 250 bpy.ops.render.render(animation=True) # 保存 save_path = os.path.abspath(os.path.dirname(__file__)) bpy.path.relpath(save_path) bpy.ops.wm.save_as_mainfile(filepath="Physical.blend", relative_remap=True) if __name__ == '__main__': delete_all() create_scene() start_simulation()
シミュレーションの設定は18行目から3パターンあります。pattern1は剛体のシミュレーション、pattern3が柔体シミュレーション。
柔体シミュレーションは「bpy.ops.object.modifier_add(type=’SOFT_BODY’)」を追加して「Cubeたちよ!君たちは柔体だ!」と定義してあげるだけ(笑)
詳しく調べていませんが、柔体用のパラメータはたくさんあると思います。上記1行ではおそらくデフォルト値が設定されるのではないかと思います。
動作画面
おわりに
Blenderは3DCGソフトウェア。本来はマウスであれこれやって作っていくもの。でも、Cubeを1000個並べるような単純な繰り返しはスクリプトを組んで実行させた方が楽。
それ以外にもスクリプトが効果的なシーンはあるでしょう。Creative Codingをやっている方もいますし。
いろんなことができるソフトウェアが(基本的に)無料で使えて遊べる。とてもありがたいことですね。