2023年9月2日土曜日

Blender:オブジェクトの衝突時に自動で効果音を付ける方法

 リジッドボディを利用してオブジェクトの衝突、落下などなどやった時に丁度良いタイミングで音が出たらいいなと思いませんか?そんな希望を叶えるアドインの紹介。これスゴイですよ。

Bake-Collisions-To-Sounds-addon:

■セットアップ
  1. リンク先から Bake-Collisions-To-Sounds.py をダウンロード
  2. Blenderを起動し、[編集]→[プリファレンス]
  3. [アドオン]→[インストール]を選択し、先ほどダウンロードしたファイルを選択し、[アドオンをインストール]
  4. インストールしたアドオンを有効化しておく

■利用方法
 アニメーション再生するとオブジェクトが衝突するように事前設定。オブジェクトを配置し、リジッドボディを設定しておきます。その時、何フレームまでのアニメーションになるのかも確認しておきます。
 アニメーションの準備ができたら以下を操作。

  1. アニメーションの対象となるオブジェクトを選択状態とする(ココ重要)
  2. [F3]を押して、検索窓に[キーフレーム]と入力。[キーフレームにベイク]を選択。※英語環境の場合、[Bake to Keyframes]
  3. 事前にアニメーションで確認した最終フレーム数に変更して[OK]。1フレーム毎にキーフレームが設定されます。
  4. 画面上部[オブジェクト]→[Bake Collisions To Sounds]でアドインを起動
  5. パラメタについては以下を参考に設定します。
    • [トラック]はまずは"1"に。
    • [ボリューム]は名前の通り。まずは10~30ぐらいの大き目が良いです。理由が後程。
    • しきい値は、小さいほど衝突と判定しやすくなり、音がたくさん挿入されます。0.1前後でオブジェクトに合う値を探してください。
    • フレーム範囲は事前に確認したアニメーションのフレームを設定します。
    • ファイルは、[ファイル名]カンマ[オフセット]の形で指定します。例えば、"c:\tmp\sound.mp3, +10"とか。オフセットは、衝突を検出したフレームからどれだけフレームをずらして音をセットするのかを指定します。最初は"+0"で良いです。オフセットの指定を忘れるとエラーになります。
    • 最後に[OK]を押せば効果音の挿入完了です。
  6. アニメーションを再生させれば合わせて音が出ます。アニメーションレンダリングすれば音付きのアニメーションが出力されます。


まずはキーフレームにベイクするところから。忘れがち。

ボリュームとしきい値はお好みで。ファイル名の後ろにオフセットを付けないとアドインがエラーとなります。

[Video Editing]で挿入された効果音を確認できます。複数の効果音が密集して挿入されているので、枠が重なった状態で表示されています。

■TIPS

  • オブジェクトを編集した場合はキーフレームのベイクからやり直します。音付けだけやり直す場合は、Video Editing Windowから挿入された効果音を削除してアドインを再実行します。
  • 衝突判定の仕組みはオブジェクトの位置の変化を見ています。各フレームで、対象フレームと前2フレームからオブジェクトの位置を確認し、一定速度で移動していない場合、かつその変化が[しきい値]を超えた場合に効果音が追加されます。一定速度ではない場合に、X,Y,Z軸それぞれでチェックしており、音を変化させたい場合は、音とオフセットをカンマで続けて指定します。
  • また、位置の変化量を効果音量として設定しているので、移動変化速度=衝突速度が速いほど大きな音となります。アニメーションによっては再生音が小さく設定される可能性があるため、最初は大き目の音を設定して調整していくと良いです、と作者の方もコメントされています。

Blender x Python で作るQRコード

 URL等の文字列からキューブメッシュでQRコードを作成するスクリプトです。ザクッとQRコードを作ってから、キューブの色、ライティング、カメラアングル等いろいろ変更してみると楽しいと思います。いろいろやってみたところで、カメラアングルのお勧めは真正面からの10度ずらしです。

 ロジックとしては、「qrcode」というライブラリでQRコードの画像を生成します。その画像から、位置を指定して色を読み取り、その色に合わせて2色のマテリアルを割り当てることでQRコードを生成しています。生成した画像はどこにも現れません。

 簡単にロジックやカスタマイズ箇所をご案内します。

 冒頭"QR_BLOCK_SIZE=10"は、QRコードを生成するときの1ブロックのピクセル数です。画像からを解析するときに必要ですが、結果には影響しません。

 "QR_CODE"に文字列を指定します。お好きなURLを指定してください。

 "mat_b","mat_w"は2色のマテリアルです。黒に該当する色は濃い目の色なら何色でも構いません。濃淡を逆にすると読めないリーダーがあるようです。

 forの2重ループで、QR画像から色を読み取り、色に合うマテリアルを適用させています。色やメッシュの形はかなり自由に変更できると思います。また、カメラアングルやライティングもいろいろ試してみると面白いと思います。

#blender 3.0.0で動作確認
import bpy
import qrcode

#全部メッシュの削除
for item in bpy.data.meshes:
    bpy.data.meshes.remove(item)

QR_BLOCK_SIZE = 10
QR_CODE = "https://oneonet-blog.blogspot.com/"

qr = qrcode.QRCode(box_size=QR_BLOCK_SIZE, border=0)
qr.add_data(QR_CODE)
qr.make()
img = qr.make_image(fill_color="black", back_color="white")
img_size,img_size_dummy = img.size
qr_size = img_size // QR_BLOCK_SIZE

mat_b = bpy.data.materials.new("Black")
mat_b.diffuse_color = (0, 0, 0, 1.0)

mat_w = bpy.data.materials.new("White")
mat_w.diffuse_color = (1, 1, 1, 1.0)

for z in range(qr_size):
    for x in range(qr_size):
        x_pos = x * QR_BLOCK_SIZE+1
        z_pos = z * QR_BLOCK_SIZE+1

        bpy.ops.mesh.primitive_cube_add(location=(x,0,qr_size - z), scale=(0.5, 0.5, 0.5))

        if img.getpixel((x_pos, z_pos)):
            bpy.context.object.data.materials.append(mat_w)
        else:
            bpy.context.object.data.materials.append(mat_b)





2023年9月1日金曜日

Blender ドミノアニメーションに自動で効果音を付けてみた

オブジェクトの衝突に合わせて効果音を設定するアドインを使って、ドミノ倒しに効果音を設定してみました。これはほんとにスゴイとしか言いようがないです。最後のドミノが倒れた後の「トコトコン♪」部分最高じゃないですか。

Blender:オブジェクトの衝突時に自動で効果音を付ける方法 

■前準備

ドミノの並べるスクリプトもしくは自分で並べてドミノ倒しを準備しましょう。ポイントはリジッドボディですね。面倒な方は以下をご利用ください。工夫としては、ドミノの隙間を少しづつ短くしている点です。これにより音の出る間隔が短くなるはずで、それに合わせて効果音が短い間隔で再生されることがお分かり頂けるかと思います。

#blender 3.0.0で動作確認
import bpy

for item in bpy.data.meshes:
    bpy.data.meshes.remove(item)

bpy.ops.mesh.primitive_plane_add(size=400,  align='WORLD', location=(0, 0, -5), scale=(1, 1, 1))
bpy.context.object.rotation_euler[2] = 0.78

bpy.ops.rigidbody.object_add()
bpy.context.object.rigid_body.type = 'PASSIVE'

for i in range (0 ,100 ):
    bpy.ops.mesh.primitive_cube_add(location=(-200+i*5-((i/10)**2) , 0, 0), scale=(1,4,10) )
    bpy.ops.rigidbody.object_add()
    bpy.context.object.rigid_body.friction = 1
    if i==0:
        bpy.context.object.rotation_euler[1] = 0.3


■効果音設定

例のアドインで効果音を設定します。ポイントは[しきい値]で、落下等の衝突より移動が少ないので、値は「0.01」ぐらいを目安にしてください。落下するより動きが少ないため、「0.1」だと衝突として検出せず効果音が設定されません。音源はドミノの倒れる音が良いとは思いますが、あえて違う音を設定してみました。今回は、WindowsPCにUSBデバイスを接続した時の音です。効果音次第で楽しめそうな気がします。

アドインにより効果音を設定した後の設定です。効果音の間隔が短くなっていることがおわかり頂けるかと思います。最後の「トコトコン♪」はこうなってます。


■アウトプット

こうなります。ドミノを並べるところから、効果音を設定するまで全て自動化されています。つまり、どこまでも長く、大きくできるということです。




Blender x Python pipでのライブラリインストールの方法

 BlenderとPythonが同時にインストールされているとなんとなくややこしくなるPythonのライブラリ管理。BlenderのPythonにインストールする方法のご案内。Blenderのバージョンによってパスが違ってきますのでご注意。現時点最新の3.0だとこうなります。

前準備:
管理者モードのコマンドプロンプトを準備します。

カレントディレクトリ:
C:\Program Files\Blender Foundation\Blender 3.0\3.0\python\bin

コマンド:
python -m pip install [ライブラリ名] -t "C:\Program Files\Blender Foundation\Blender 3.0\3.0\python\lib\site-packages"



Blender x Python で作る途中で模様が出てくる玉転がし

 2000個の玉をぶちまけてくるくる回っているところを見ていると何故か模様が浮かび上がる映像です。玉が転がる状況は好きに作ってもらえばいいですが、床板、ガードレール、大量の玉を配置するスクリプトを張っときます。前準備に特別なことはないので見れば何してるかわかるかと思います。

 ポイントは準備ができたらアニメーションをスタートし、お好みのフレームでいったん止めます。そのあとオブジェクトモードになっていることを確認して"C"キーを押します。これによりボックス選択ではなくサークル選択選択モードになりますので、マウスホイールでサイズを調整してから、対象としたいメッシュをまとめて選択します。その後マテリアルプロパティでお好きな設定をした後、"マテリアルを選択物にコピー"を選ぶことで、選択したメッシュに全て同じマテリアルが適用されます。サークルである必要はなく、1つ1つクリックして選択するなりしてください。ポイントはアニメーションを途中で止めてその瞬間にちゃんと見えるように指定するところです。

 カメラ、ライトはお好きに設定しましょう。見下ろす感じのアングルがよろしいかと思います。 





#blender 3.0.0で動作確認
import bpy

#全部メッシュの削除
for item in bpy.data.meshes:
    bpy.data.meshes.remove(item)

f = 200

#床板
bpy.ops.mesh.primitive_plane_add(size=20, enter_editmode=False, align='WORLD', location=(0, 0, -1), scale=(1, 1, 1))
bpy.ops.rigidbody.object_add()
bpy.context.object.rigid_body.type = 'PASSIVE'
bpy.context.object.rigid_body.friction = 0.0

#注ぎ口
bpy.ops.mesh.primitive_plane_add(size=3, enter_editmode=False, align='WORLD', location=(3, 7, 3), scale=(1, 1, 1))
bpy.ops.rigidbody.object_add()
bpy.context.object.rigid_body.type = 'PASSIVE'
bpy.context.object.rigid_body.friction = 0.0
bpy.context.object.rotation_euler[1] = -0.5
bpy.context.object.rotation_euler[0] = 0.5

#ガードレール 
for z in range (0,10):
    bpy.ops.mesh.primitive_torus_add(align='WORLD', location=(0, 0, -0.5+z*0.5), rotation=(0, 0, 0), major_radius=10, minor_radius=0.1)
    bpy.ops.rigidbody.object_add()
    bpy.context.object.rigid_body.type = 'PASSIVE'
    bpy.context.object.rigid_body.friction = 0.0
    bpy.context.object.rigid_body.collision_shape = 'MESH'

#注ぎ口の上に落ちる球を積み上げる 3×3を200段
for z in range (0,f*3,3):
    for x in range (0,3):
        for y in range (0,3):
            bpy.ops.mesh.primitive_uv_sphere_add(radius=0.5, enter_editmode=False, align='WORLD', location=(x+2, y+6, z+10), scale=(0.5, 0.5, 0.5))
            bpy.ops.rigidbody.object_add()
            bpy.context.object.rigid_body.collision_shape = 'SPHERE'
            bpy.context.object.rigid_body.friction = 0.0