はじめに
Twitterのヘッダーイメージを作成している際のメモです。
パーティクルと物理とアニメーションノードを使った作業です。
イメージの助けとなるかわかりませんが作業中の一部分を抜粋した動画です
最終結果
この記事ではツイッターアイコンではなくスザンヌを放出させる手順と注意事項を紹介します。
参照元
概要
箱の中にブロック状のTwitterアイコンがランダムに詰められているイメージを作成しようと思い、Blenderのパーティクルを使ってオブジェクトをランダムに放出して、放出したオブジェクトに物理(Rigid body)特性を持たせて落下させています。
Animationノードを使っているのは放出後に物理特性をつけるため。
この記事では参照元の動画を行った際のメモです。話を簡単にするためTwitterアイコンではなくスザンヌを使用してまとめています。
補足
Animationノードを使わなくてもできます。しかし放出するオブジェクトとして用意したオブジェクトに物理特性をもたせ、それを放出する事で放出されるオブジェクト全てに物理特性がつくかというとそうではなく、放出される段階で物理特性はコピーされません。物理特性を付けたい場合は、放出された後に一時停止して放出された各オブジェクトを選択して物理特性(Rigid Body化)するという作業が一般的なようです。
Animation nodes には全く同じ作業ではありませんが、代替手段を自動で行ってもらうために使っています。
用意するもの
- ランダムに放出されるオブジェクト
- 放出元となるエミッター
- 放出されたオブジェクトを入れる箱(Rigid Body passive)
- アニメーションノード(インストールされている事)
- dを除くオブジェクト類を配置した図
設定手順
a. ランダムに放出されるオブジェクト
- スザンヌを選択して物理プロパティパネルから Rigid Bodyをクリック
- TypeをActiveにする。(動く物体のため)
- Dynamic のチェックを外しAnimatedにチェックを入れる
- Dynamic = Blender側でシュミレーションする
- Animated=作成者側で動きを制御する。という認識
- Shape を Meshにする
- 複雑な形状を持つ物体である事を示しており衝突時の動きに影響する
b. 放出元となるエミッター
- エミッターを選択してパーティクルプロパティーパネルから + (追加)をクリック
- Numberは30とする。
- 30はここではスザンヌを生成する数となる。
- 大きいと負荷が高くなり動作が重くなる為、動作確認中は低い数字にとどめておくのがよい
- Frame Start と End は放出開始時間と放出終了時間。
- Animation Nodeで制御する為、0として放出させない
- ここではエミッター上のランダムなポイントを得るためだけにパーティクルシステムを使用している
- Lifetimeは1000としてシュミレーション中はパーティクルが消えないようにしている
c. 放出されたオブジェクトを入れる箱(Rigid Body passive)
- 箱を用意。(Scale、Inset、Extrudeで作成)
- 箱を選択して物理プロパティパネルから Rigid Bodyをクリック
- TypeをPassiveとする((土台となる物体のため)
- Shape を Meshにする
- 複雑な形状を持つ物体である事を示しており衝突時の動きに影響する
d. アニメーションノード
大きく分けて3つのセクションからなる。
順に詳細を見ていく前に概要を記載する。
- 一番上はメインルーチン部分で、一気にパーティクルを落とすのではなく1フレームから100フレームの間のどこかで落とすようにしている
- 中央は引数として渡されたオブジェクトリストの物理特性をBooleanに基づいて変える部分
- 一番下はパラメータとして渡されたオブジェクトの可視性を変える処理
ここでは逆の順序で一番下から上に見ていきます。
作業の前に
左側のパネルの Auto Execution のチェックを外し、下にある Tree Changed、Frame Changed、Property Changedにチェックを入れてください。
こうしなければ毎フレームノードツリーが実行され、PCからのゴリゴリ音が常に聞こえてきます。
パラメータとして渡されたオブジェクトの可視性を変えるループ作成
詳細
- Subprogram のGroupを配置
- New Input の + をクリックして Object List を選択
- Object List内に対してなんかしらの処理をするという意味
- New input の + をクリックしてBoolean を選択
- 名前を SetVisible とする
- Invert Boolean を配置して引数を Boolean を接続
- Boolean を反転させる
- Object Visibility Output を配置
- オブジェクトの可視性を変えるノード
- New Generator Output をクリックして Object List を選択
- このループの戻り値となるノード
- 全てを最初の画像のとおり接続
渡されたオブジェクトリストの物理特性をBooleanに基づいて変える部分
実装詳細
- Subprogram のGroupを配置
- New Input の + をクリックして Object List を選択
- Object List内に対してなんかしらの処理をするという意味
- New input の + をクリックしてBoolean を選択
- 名前を TurnOnOff とする
- Set Visible を配置
- Object Attribute Output を配置し、
rigid_body.enabled
と入力- Rigit Body の Dynamic のフラグ を設定するという意味
- この文字列はパネル上の Dynamic を右クリックして、Copy Data Pathからコピーする事が可能
- Object Attribute Output を配置し、
rigid_body.kinematic
と入力- Rigit Body の Animated のフラグ を設定するという意味
- この文字列はパネル上の Animated を右クリックして、Copy Data Pathからコピーする事が可能
- Invert Boolean を配置して引数を Boolean を接続
- Boolean を反転させる
- Object Attribute Output を配置し、
rigid_body.collision_collections
と入力- Rigit Body の Collision group への参加/非参加の切り替えるという意味
- この文字列はパネル上の Collision groupを右クリックして、Copy Data Pathからコピーする事が可能
- Create Boolean List ノードを配置しList数が20になるまで New Input を押す
- New Generator Output をクリックして Object List を選択
- このループの戻り値となるノード
- 接続する
実装解説
- TurnOnOffサブプログラム はObject List と単一の値を取る
- まず渡されたオブジェクトリストを Set Visible に Boolean と一緒に渡し、Booleanの値で可視性を設定してもらう
- 次にDynamic と Animated のチェックを入れ替える処理を行う
- オプションは常にテレコになるため Invert している
- 次は Collision Group への参加/非参加を表明する処理
- Collision Groupは計20個あり、どれに参加するかを示す必要がある。
- この実装ではグループの一個目に参加または非参加とするため、一個目のみ値を引数で定義するようにしており、残りの19個は常にFalse(非参加)である事を示している
- Collision Groupは計20個あり、どれに参加するかを示す必要がある。
- 最後に処理が完了したObject Listを返している
メインルーチン部分
そこまで複雑ではないため解説と実装を同じにする
詳細
- Particle System from Object を配置
- Particles Data を配置
- Alive のみにチェックを入れているのはStart/End が共に0のため、0フレーム目で全パーティクルが作成され、Lifetimeが1000のため、1000フレームを超えない限りDeadにならないため。
- パーティクルの個数を取得するためGet List Length を配置
- オブジェクトを複製するため、Object Instancerを配置し Suzanne を選択。Copy Full Objectにもチェックを入れる
- オブジェクトのトランスフォーム(位置、回転、スケール)を設定するため、Object Transform Outputを配置
- Random Number を配置しVector from Value で単一のfloat を(float,float,float)の情報に変換し、Scaleに接続
- ランダムに回転させるためRandom Euler を配置し Rotation に接続
- Object Transform Output の Location は Particles Data の Location を接続
- TurnONOffの呼び出しのため、Subprograms の Invoke Subprogram にある TurnOnOff を配置。
- リストから一部だけを切り取ったリストを作成するため、Slice Listを配置
- 開始位置は固定でEndだけを指定するため End にチェックを入れる
- これで常に 0 ~ n までのリストが取得できる
- 開始位置は固定でEndだけを指定するため End にチェックを入れる
- Math Divide(割り算)を配置。Get List Length を Aに接続し、Bを100とする。
- 全パーティクルを100フレーム間で放出すると考えた場合の1フレームで出すパーティクル量を算出
- Math Multiply(掛け算)とTime Infoを配置し、MultiplyのAにはDivideの結果、BにはTime infoを接続。出力は Slice List に接続
- Time infoが増える毎に放出するパーティクルの数も増えていく
- Slice List で出力された一部のリストに対し物理特性を付与するため TurnOnOff を配置。Boolean はチェックを入れておく
実装完了!
使用方法
- End フレームを180に設定
- 参照元の動画に従っていますが使用方法がわかったら好きな数値でやってみてください。
- Scene プロパティパネルの Rigid Body World を無効化
- Animation nodeのAuto Execution を有効化
- Bake to Keyframesをクリック
- Animation NodeのAuto Executionを無効化
- これによってAnimation側が行う仕事のベイクは完了
- 何フレーム目にどういったスケールや回転でパーティクルを放出するかは直にフレームに書き出された状態
- もうAnimationNodeに動作してもらうことは無いため無効化する
- 逆に無効化をしないと競合が起きて挙動が変になる可能性があります
- これによってAnimation側が行う仕事のベイクは完了
- Rigid Body World を有効化
- CacheのEndフレームを180に設定
- Bake を押す
- 再生すると物理が働いている事が確認できるG
- 生成されたオブジェクトを全選択する為、生成されたオブジェクトを1つ選択し、Shift + Gで Collection をクリック
- Animation nodes Object Container をクリック
- 抄出されたオブジェクトがすべて選択される
- Object メニュ → Rigid Body → Bake to Keyframes でベイクする
完了。
- 1番目のベイクはAnimation nodeの作業をベイク
- 2番目のベイクは全てのフレームについてどのようなオブジェクトが物理演算をする対象となっているかという情報のベイク
- 3番目のベイクは物理演算の結果オブジェクトがどのように空間上に配置されたかという情報のベイク
という事で完了ですが、別の条件で行いたい場合、ベイクしたデータなどを削除し再度この使用手順を行う事になります。
削除手順です。
ベイクデータ削除手順
- タイムフレームは最後にしておく
- ドープシート画面を開く
- a で全てを選択→ x で keyframe の削除を実行(delete keyframe)
- Rigid Body Worldを無効化しDelete Bakeする
- 参照元の動画では特になかったと思いますが、Animation nodesによってえ作成された全てのオブジェクトも削除する事をおすすめします
削除完了です
最後に
すぐに思った通りにできるわけではなく結構試行錯誤を要求されると思います。
いくつか詰まった点を書いておきます
パーティクルのサイズ
箱として機能してもらう Passive の Rigid Body はイメージ的にはメッシュ状(網目状)になっていてあまりにパーティクルが小さいとすり抜けていきます。
Passiveの受け皿について
Meshという形状が使いにくい為、もししたら5つのBoxタイプのPassiveで間を囲んだほうがいいかもしれません。
放出されるオブジェクトのソースのサイズと回転
放出されるオブジェクトのソースのサイズは(1, 1, 1)、回転は(0, 0, 0)としておかないときれいに動作しないと思います。
放出されるオブジェクトのソースの移動について
オブジェクトの移動はオブジェクトモードで行いましょう。Editモードで編集すると Collisionは0,0,0のままだけど目に見えるオブジェクトは原点からずれているため、見た目がかなりおかしくなります
– 上は編集モードで横にずらしたボックスですが、Collisionは中央のままです。
メモ
SubprogramのLoopとGroupどちらを使えばよいのか?
- 個別の条件で処理を分けたい場合はLoop。一括で同じ処理をする場合はGroupを使用する。
- 例えばオブジェクトを10個持つリストがありリストの内X座標が1より大きいオブジェクトは処理A、そうでなければ処理Bなどとしたい場合はLoop。
- ノードによっては入力に単一オブジェクト、オブジェクトリストどちらも渡せるノードがあるが、時には単一オブジェクトしか渡せないノードもある。その場合は Loop を作成しループ内でそのノードに処理してもらう必要がある
検索エンジン用
効果があるかわかりませんが、英語バージョンも記載しておきます
- particle
- physics
- AN