執筆者:廣瀬
映像業界を経てモノリスソフトへ入社。 以来、テクニカルアーティストとして主にエフェクト関連の業務を担当。 好きな食べものはソフトクリーム。
TECH BLOG
こんにちは。モノリスソフト テクニカルアーティストの廣瀬です。
今回はHoudinを使い様々な方法で斜方投射(俗に言う、砲丸投げの軌道・スパークとか)を作ってみます。
この記事では、
の3種類で作ってみます。
斜方投射というシンプルで基礎的な題材ですので、HoudiniのPOPがよくわからない方や、エフェクトアーティストの方の再学習などにお役立てください。
サンプルファイル(monolithtech_solver.zip 43.4 KB)はこちらです。
ネットワーク上から見ていきます。
任意の数のポイントを作成します。
今回はここで作成したポイントを使ってシミュレーションを行います。
Point Generate SOPノードで作成したポイントに初速度のアトリビュートを作成します。
今回はY軸に対してコーン状の初速度を作成しています。
Attribute Nameの v はHoudiniでは慣例的に1秒の間に進む速度として扱われます。
Attribute Randomize SOPノードで作成した初速度を適当にトランスフォームしています。
トランスフォームと言われると位置移動のイメージがありますが、速度もこのノードでトランスフォームすることができます。
HoudiniではP, N, v, orient など慣例的に使用するアトリビュートにはアトリビュートタイプのメタデータが設定されていて、Transform SOPノードなどはこれらの情報を元に適切にトランスフォームを行ってくれます。もちろん、アトリビュートタイプメタデータはユーザーが新たに作成したアトリビュートにも設定することができ、Attribute Create SOPノードなどを使って指定することができます。
これで初期セットアップは終わりです。
ここから先は様々な方法でシミュレーションをしてみます。
まずは、POPを使用した方法です。
POPはHoudiniのパーティクルシミュレーションシステムです。
POPでは毎フレームポイントが追加されてしまうので、このノードで開始フレーム以外はポイントをなくして毎フレームポイントを追加されなくしています。
他にも後述するDOP Network SOPノード内で、POP Source DOPノードのInpulse Activationパラメーターを設定したり、Enable Solver DOPノードやGas Intermittent Solve DOPノードを使用する方法などもあります。
DOP Network SOPノードをダブルクリックしてDOP Networkに入ります。
パーティクルシミュレーションに必要なデータ構造を定義しています。
パーティクルを毎フレーム追加しています。俗に言うエミッターです。
ここではDOP Network SOPノードの1番目の入力、つまりSwitch SOPノードのジオメトリ情報を取得してパーティクルとして追加しています。
パーティクルシミュレーションのソルバーです。速度や位置の更新、コリジョンなどが適応されます。
積分計算はオイラー法が採用されているようです。
パーティクルに重力を適応しています。
続いて、Solverを使用した方法です。
Solverは自前の積分計算を作成できるノードです。
Solver SOPノードをダブルクリックして中に入ります。
前フレームのジオメトリ情報を取得しています。
ポイントに限らずライン・メッシュ・NURBS・ボリュームなどSOPジオメトリは何でも前フレームの情報を取得できます。
自前で積分計算を実装しています。
今回はPOPに合わせてオイラー法で実装しています。
@TimeInc は時間刻み幅 (Δt) です。これはFPSやサブステップなどを加味した適切な値が入っています。
@v はセットアップで作成していた速度アトリビュートのことです。重力を毎フレーム追加して上書きしています。
@P はポイントの位置です。速度を毎フレーム追加して上書きしています。
最後に、VEXを使用した方法です。
斜方投射を数値的ではなく解析的に解いて、シミュレーションせずに位置と速度を算出しています。
よくよく見ると高校物理の内容のはずなので、それを思い出しならコードを読んでみてください。
float g = -9.80665; // 重力加速度(m/s^2) float t = @Time; // 現在の時間(秒) float vw0 = length(set(@v.x, @v.z)); // 横方向の初速 (m/s) float vh0 = @v.y; // 縦方向の初速 (m/s) float vw = vw0; // 時間tでの横方向の速度 (m/s) float vh = (g * t) + vh0; // 時間tでの縦方向の速度 (m/s) float pw = t * vw0; // 時間tでの横方向の位置 (m) float ph = (0.5 * g * t * t) + (t * vh0); // 時間tでの縦方向の位置 (m) float x = @v.x / vw0; float z = @v.z / vw0; @v.x = vw * x; @v.y = vh; @v.z = vw * z; @P.x = pw * x; @P.y = ph; @P.z = pw * z;
Merge SOPノードを表示すると各手法の結果を同時に見ることができます。
微妙に結果がずれているのは、数値解 (シミュレーション) と解析解のずれです。
エフェクトアーティストの方は、シミュレーションで円運動などを作ろうとしたときに、速度をちゃんと設定しているつもりなのに、円の軌道からずれていってしまった経験はありませんか?
それは、まさにこれが原因です。
これはDOP Network SOPノードや Solver SOPノードのサブステップを上げると解析解に近づいていく様子を見ることができます。
サブステップをあげる以外の手法としては、1フレーム後の目的の位置に行くように速度を強制的に設定してしまうことです。以下のような計算です。
@v = (@Pnext frame - @Pcur frame) / @TimeInc;
この方法は、きれいな円運動を行いたいときなどに、著者もよく使用したりします。
また、Trail SOPノードでポイントの軌道を見ることができます。
今回は様々な方法で斜方投射を作成してみました。
一つの斜方投射をとっても、様々な方法で実装することができる柔軟性もHoudiniの魅力の一つです。
この記事が、HoudiniのPOPの理解や、エフェクトアーティストの方の再学習の手助けになりましたら幸いです。
執筆者:廣瀬
映像業界を経てモノリスソフトへ入社。 以来、テクニカルアーティストとして主にエフェクト関連の業務を担当。 好きな食べものはソフトクリーム。