映画『神さまの言うとおり』(2014)
ほんと怖すぎです。イケメンが出てくるからって安心しないでください。(R15+)で、スプラッターなので視聴に注意が必要です。
楽しいゲームがたくさん用意されているのですが、そのゲームに負けてしまうとデス! つまり生き残ることができないのですが、ほとんどの高校生が失敗して果てます。男子も、女子も、美男子でも、美少女でも、差別なく酷いことされます。
私は初めて試聴したときは、ダルマのシーンでリタイヤして、続きを見ないままレンタルへ返却しました。当時ダルマが怖くて眠れなくなりそうだったので、怖くないダルマをBlenderでPythonプログラミングしてみようと思い、本記事を書いた次第です。
さて怖くないダルマを使って、Blenderでダルマ落としをチャレンジしてみます。
Contents
1. ダルマのマッピング画像を準備する
ダルマ画像としてこのように塗り絵を作りました。
2. z方向の重力を大きくする
重力が小さいままだと、ダルマが浮き上がってしまいますので、大きい数字(マイナス)にします。
bpy.data.scenes["Scene"].gravity.z=-50
3. 最初からあるCubeを地面に変形する
Cubeを変形して地面にしたら、PASSIVEタイプの剛体にします。
bpy.data.objects['Cube'].location=(0,0,-2) bpy.ops.transform.resize(value=(9,9,1)) bpy.ops.rigidbody.object_add(type='PASSIVE')
4. 新規に円柱を追加してダルマにする
円柱を追加したら、UVマッピング用の切れ込みを入れます。
bpy.ops.mesh.primitive_cylinder_add()
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_mode(type='EDGE')
mesh=bmesh.from_edit_mesh(bpy.context.object.data)
bpy.ops.mesh.select_all(action='DESELECT')
mesh.edges[0].select = True
for i in range(0,32):
mesh.edges[i*3+1].select = True
mesh.edges[i*3+2].select = True
bpy.context.scene.objects.active = bpy.context.scene.objects.active
bpy.ops.mesh.mark_seam()
mat=bpy.data.materials.new('Material.001')
mat.emit=1
tex1 = bpy.data.textures.new('Tex1', type='IMAGE')
fname=os.path.expanduser('~/dharma.png')
tex1.image = bpy.data.images.load(fname)
bpy.context.object.data.materials.append(mat)
mt=mat.texture_slots.add()
mat.texture_slots[0].texture=tex1
mt.texture_coords='OBJECT'
bpy.data.materials['Material.001'].texture_slots[0].texture = tex1
bpy.data.materials['Material.001'].texture_slots[0].texture_coords='UV'
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.uv.unwrap()
5. ダルマを剛体にする
ダルマをACTIVEタイプの剛体にします。一番下のダルマが飛ばされたときに、上のダルマが真下に落ちるように細かい設定をします。
bpy.ops.rigidbody.object_add(type='ACTIVE') cy.rigid_body.use_deactivation=True cy.rigid_body.use_start_deactivated=True cy.rigid_body.collision_shape="CYLINDER" cy.rigid_body.use_margin=True cy.rigid_body.collision_margin=1
6. ダルマをコピーして増やす
ダルマをコピーしていきます。スクリプトの見せ場ですね。
for i in range(0,100): bpy.ops.object.duplicate() bpy.ops.transform.translate(value=(0,0,2))
7. ダルマ落とし用ハンマーを作る
ダルマ落とし用ハンマーっていっても、ただの床にくっついている四角い棒です。
Cubeを追加して、細長くします。ACTIVEタイプの剛体にしますが、collision_shapeをMESH型にしないと、なぜかダルマをすり抜けることがあります。
bpy.ops.mesh.primitive_cube_add() bpy.ops.transform.resize(value=(9, 0.2, 1)) bpy.ops.rigidbody.object_add(type='ACTIVE') bpy.data.objects['Cube.001'].rigid_body.kinematic=True bpy.data.objects["Cube.001"].rigid_body.collision_shape="MESH"
8. フレームを設定して、ハンマーを往復移動させる
フレーム番号を設定したら、ハンマーを所定の場所に移動させ、キーフレームを設定します。
往復するために方向(direction)が交互に変わります。
direction=-1 for i in range(1,10): bpy.context.scene.frame_set(i*20) bpy.ops.transform.translate(value=(0,direction*18,0)) bpy.context.active_object.keyframe_insert(data_path="location", index=-1) direction= -direction

9. 完成スクリプト
全部を通したスクリプトはこれです。
~$ cat dharma.sh
#!/bin/bash
cat <<EOL>/tmp/tmp.py
import bpy,bmesh,math,os
bpy.data.scenes["Scene"].gravity.z=-50
bpy.data.objects['Cube'].location=(0,0,-2)
bpy.ops.transform.resize(value=(9,9,1))
bpy.ops.rigidbody.object_add(type='PASSIVE')
bpy.ops.mesh.primitive_cylinder_add()
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.select_mode(type='EDGE')
mesh=bmesh.from_edit_mesh(bpy.context.object.data)
bpy.ops.mesh.select_all(action='DESELECT')
mesh.edges[0].select = True
for i in range(0,32):
mesh.edges[i*3+1].select = True
mesh.edges[i*3+2].select = True
bpy.context.scene.objects.active = bpy.context.scene.objects.active
bpy.ops.mesh.mark_seam()
mat=bpy.data.materials.new('Material.001')
mat.emit=1
tex1 = bpy.data.textures.new('Tex1', type='IMAGE')
fname=os.path.expanduser('~/dharma.png')
tex1.image = bpy.data.images.load(fname)
bpy.context.object.data.materials.append(mat)
mt=mat.texture_slots.add()
mat.texture_slots[0].texture=tex1
mt.texture_coords='OBJECT'
bpy.data.materials['Material.001'].texture_slots[0].texture = tex1
bpy.data.materials['Material.001'].texture_slots[0].texture_coords='UV'
bpy.ops.mesh.select_all(action='SELECT')
bpy.ops.uv.unwrap()
cy=bpy.data.objects['Cylinder']
cy.rotation_mode='XYZ'
cy.rotation_euler=(0, 0, math.pi/2)
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.rigidbody.object_add(type='ACTIVE')
cy.rigid_body.use_deactivation=True
cy.rigid_body.use_start_deactivated=True
cy.rigid_body.collision_shape="CYLINDER"
cy.rigid_body.use_margin=True
cy.rigid_body.collision_margin=1
for i in range(0,100):
bpy.ops.object.duplicate()
bpy.ops.transform.translate(value=(0,0,2))
bpy.ops.mesh.primitive_cube_add()
bpy.ops.transform.resize(value=(9, 0.2, 1))
bpy.ops.rigidbody.object_add(type='ACTIVE')
bpy.data.objects['Cube.001'].rigid_body.kinematic=True
bpy.data.objects["Cube.001"].rigid_body.collision_shape="MESH"
bpy.context.scene.frame_set(1)
bpy.ops.transform.translate(value=(0,9,0))
bpy.context.active_object.keyframe_insert(data_path="location", index=-1)
direction=-1
for i in range(1,10):
bpy.context.scene.frame_set(i*20)
bpy.ops.transform.translate(value=(0,direction*18,0))
bpy.context.active_object.keyframe_insert(data_path="location", index=-1)
direction= -direction
bpy.context.scene.frame_set(1)
bpy.data.objects['Camera'].location=(10,-9,10)
bpy.data.objects['Lamp'].location=(3,-4,5)
bpy.data.lamps['Lamp'].distance=2000
EOL
blender -b -P /tmp/tmp.py -o //test -a -F PNG -x 1 -f 1 | grep ^Save
convert -layers optimize -loop 0 -delay 5 test????.png test.gif
10. 実行すると
上のスクリプトを実行すると、このようなGIFアニメができます。
見事にダルマ落としチャレンジ失敗しました。
あれから本映画を最後まで試聴してみましたが、やはり怖いものは怖いです。
本記事のダルマ落とし失敗の動画を見て気を紛らわしました。

コメント