忙しくて書きかけの記事を放置していたらインディゾーンさんのブログに記事が追加されていました。
Houdini 18.5でのガイドシミュレーション | インディゾーンHoudini情報日本語ブログ
ここは自分への備忘録でやり方も若干違うため記事を投稿します。
Houdini18.5からRBD Bullet Solver(SOP)を使用せずにRBD Guide機能が使えるようになりました。
待望の更新なのでかなり嬉しいです。
- 最初に
- RBD用メッシュ
- Guide用メッシュ
- GuideのDeform
- RBD Guide Setup
- Sim
- Simがもし動かない場合
- RBD Guideの変更箇所
- Sim -Constraintの追加
- Constraintエラーの回避
最初に
この件はインディゾーンさんのブロクにも記載されていますが、Guide Geometryが単一のメッシュの場合、正確に認識できないようです。
nameがなければAsembleでnameを作成しているようなので単一ピースの場合1つのnameしか作成されない〜からの処理の流れでなっていると思います。

なのでインディゾーンさんの記事のようにBooleanで複数のピースが作成できるようにするか、分割数の少ないVoronoi等でざっくりピースを割ってあげる必要があります。
RBD用メッシュ


あとで使用するためにConstraintも作成しています。
下部をactive==0で壊れないように設定しています。

Guide用メッシュ


GuideのDeform

RBD Guide Setup

第一入力にnameを持たせてPackしたRBD用メッシュを接続します。
第二入力にConstriantを接続します。
第三入力は必要であればProxy Geometryを接続します。(個人的にはほぼ繋がないです)
第四入力にGuide Geometryを接続します。
Setupタブ

Start / End Frame : Guideアニメーションの開始終了フレーム。この範囲内でGuideに追従する。適切に設定しておいたほうが良い。
Mode : 追従させるGuide Geometryを探す基準、Near PointはGuideの中心までの距離ベース。Near SurfaceはGuideの面ベース。Volumeはよくわからない。
Max Distance : Guideを探す距離の最大値。この値を超えるとGuideを探さない。-1はこの設定を無視するということなので、どんなに遠くても必ず1つは見つける。
Strength : 距離に応じて強さを乗算する。これはひとつ下のDistance to Strengthと一緒に使う。
Distance to Strength -Distance : 強さを乗算する距離の最大最小値
Distance to Strength -Strength Mutiplier : 最大最小間での乗算する値
Blend : Guideに追従する具合を設定。(各ピースごとに設定したい場合は、Use VEXpressionsで設定する。)
Neighboprsタブ
Guideの精度とエラー回避のものっぽいが効果がよくわからない...
適切に設定すると各Guide Geometryごとに最小の接続数が設定できたりするので、Guide追従しないで動かないor追従しすぎるピースを回避できるらしい。
Constraintタブ
後述に若干追記あります。
Remove Intra-Guide Constrains : チェックを入れると同じGuide Geometry内のConstraintを削除する。


Constraint Group : ↑を適応するグループ名
このConstraintはうまく使わないと事故が起きそうだった。
Glue-Softの切り替え設定しているConstraintも削除されてしまうため、下手に設定するとConstraintを一切しないピースになる。
Sim

Pre-SolveとPost-Solveに違う設定の「RBD Guide」ノードを接続する。
Pre-Solveのほうは、Guideタブを使用し、Un-Guideはオフにして使用しない。
Post-Solveのほうは、Guideタブはオフにして使用せず、Un-Guideはオンで使用する。
どちらもInputタブはGuide SourceにGuide Geometry(RBD Guide Setupの第四出力)を指定し、Post-Solveの方はGeometry SouceにRBD用メッシュも指定する。


インディゾーンさんのブログではPre-Solveだけに接続していました。
PreSolveに「RBD Guide」を接続して、Guide,Un-Guide,Inputの全タブを設定してもRBD Guide処理は動作します。
しかし、Exampleのシーンでは、Guideへの追従はVelocity とTarget Velocityに影響を与えるためPre-Solveで行うこと。
Un-Guide処理はPre-Solveでも実行できるが、Post-Solveで実行する方をおすすめする。と書いてあるのでこちらの手法で記事を書いています。
コリジョン等の処理(Solverが行う)を挟んでからガイドへの追従を切るほうが結果が良いという感じです。
ちなみに、コリジョンなどの処理をしていない場合はPreのみ、PrePost両方に分けるのどちらでもほぼ結果は変わりません。
Simがもし動かない場合
原因がよくわかってないですが、さっきまで動いていたのに突如動かない場合やそもそも動かない場合があります。
自分の場合はGuide Geometryにrestを作成すると回避できました。

timeshiftを使用しRBD Guide SetupのStartframeで止め、restを作成し、
Attribute CopyのMatch by Attributeでnameを使用しnameごとにrestを作成します。
RBD Guideの変更箇所
詳しくはヘルプを見よう。
Guiding
Method : Target Velocityに設定。Velocityのほうが正確だがコリジョンした際にジッターが出る可能性があるらしい。
Blend : Guideへの追従具合。下げるとジッターが減るらしい。1の完全追従だと後述のGuideが動く前にずれる問題が回避はできる。
Un-Guiding
Instantaneousは即時(そのフレームの話)
Accumulatedは累積(過去の量)
Linear : Threshold : 各ピースの計算後のガイドとの位置の差
Angular Threshold : 各ピースの計算後のガイドとの角度の差
Distance Threshold : 各ピースのガイドへの距離と静止時の距離の差
Sim -Constraintの追加

ConstraintにGlue-Softの切り替えを設定し、DOP内でConstrfaintを使用した状態で、「RBD Guide Setup」のConstraintタブ、Remove Intra-Guide Constraintsがオフだと
ピースは一切動きません。Constraint Geometryを見てみると、Glueの解除ができていないようです。
Remove Intra-Guide Constraintsをオンにしてみます。

うまくいっているように見えますが、後一歩調整したいです。
Wire frame表示をやめるとわかりやすいです。

ピース間のConstraintがない部分で自己衝突が発生してGlueが全てSoftになってしまってしまい、Guideに追従する前から動いてしまっています。

これはRBD Guide SetupのConstraintを削除するグループを指定しても回避は難しいですし、
そもそもの話、Guide Simulationしている時点でConstraintを使う意味があるのか?という問題もあります。
それでも併用したい場合もありますし、RBD Guide(DOP)のGuidingにあるBlendパラメーターを下げると同じように事前に動いてしまうため
Blendを1から下げることができない=完全にGuideに追従しかない。という状況です。
ついでにいうと全てSoftになってしまうと計算が重いです。
回避を考えてみたので一例としてのせます。
Constraintエラーの回避
restが必要なので、Simがもし動かない場合、のセットアップを済ませてください。
RBD Guide SetupのConstraintsにAtribute Copyを作成し、画像のようにつなぎます。
Copy Attributes fromがGeometryで、Copy Attributes toがConstraint Geometryです。


DOP内でSOP Solverを作成し、Constraint Networkにつなぎます。

SOP Solver内で以下のように組みます。

Object MergeでGuide GeoemtryをSOPから読み込み、
check_moveに以下のように記述し、restとPが違うかどうかをチェックします。Vectorなので精度が心配ですがまあいいでしょう。
//run over Points
i@move = 0;
if(@P != @rest) {
i@move = 1;
}
check_guideNameに以下のように記述します。__guide_nameがあるかどうかをチェックし、なければnameを使用します。
//run over Points
int check = findattribval(0, "point", "__guide_name",0);
if(check == -1) {
s@__guide_name = point(0,"name",@ptnum);
}
copy_moveは以下の設定です。

broke_glueは以下です。各Constraint Geometryで動いたかどうかをチェックし、
動いた場合に__guide_nameが異なれば違うGuideを参照しているのでGlueを削除(Remove Intra-Guide Constraintsをオンと同じ)
それ以外の動いた部分はSoft(Next Constraint)に変更という処理です。Next Constraintが設定されていない場合の回避処理は入れてません。
//run over Primitives
if(s@constraint_name == "Glue") {
int pts[] = primpoints(0, @primnum);
string name1 = point(0, "__guide_name", pts[0]);
string name2 = point(0, "__guide_name", pts[1]);
int move1 = point(0, "move", pts[0]);
int move2 = point(0, "move", pts[1]);
if(move1 + move2 == 2) {
if(name1 != name2) {
i@group_broken = 1;
}else{
i@group_soft = 1;
s@constraint_name = s@next_constraint_name;
s@constraint_type = s@next_constraint_type;
}
}
}
broke_softは以下ですが、Soft Constraintを切る条件なので好きに設定する部分です。グループの指定だけは忘れないようにします。

//run over Primitives
if(@force >= 70) {
i@group_broken = 1;
}
これでコリジョンや自分でGlueを削除しない限りはGuideが動くまではGlueが切れないため動かないように設定できます。
