たびたびアニメーションをずっと原点でしていてほしい場合などがあるので追従させたりする処理のメモ。
シミュレーションやジオメトリ作成を原点でやって実際のポジションへ追従させるとかとか。
他にもいろいろな処理があると思うけど知ってる範囲で。
hipはこちら。Alembicなどは権利的に含んでいません。
obj階層
設定は簡単だが使いづらい。追従しているGeometry内の処理がややこしかったりカメラから見た位置が分かりづらかったり。
やる場合は別のGeometryで何かを作成し、追従させるためのGeometryを用意して中でObject Merge等で読み込むほうが良さそう。
Parent
すごく単純にobj階層でコネクションする。 そうすると親子状態になるので上流の動きを継承するようになる。
やり方は2つをコネクションするだけ。
他DCC(Maya等)から持ってきたUnitの単位が違うものをobj階層でスケールしてこのように繋いでしまうと下流もスケールかかった状態になってしまうので要注意。
Constraint
Constraint Networkを作成してConstraintする。
やり方はコンストレインする方のGeometryを以下画像を参考に設定する。
A,Bの順で選択し、項目からConstraint Networkを選ぶ。
Geometry内にCHOP Networkが作成されるので、その中のノードでConstraintしたいGeometryを選ぶ。
Expression / VEXとか
結構色々ある。
こちらのメリットは、参照元の上流でスケール等をかけていたとしてもMatrixとして取り出すことで実際の移動回転値として取り出せること。
optransform
追従したい方のSOPで以下のように組む。Wrangleを見ればわかるが、これのメリットは参照する時間軸をずらすことができること。
遅れたり早かったりということが手軽にできる。
Attribute WrangleのRun OverをDetailに変更し以下のように記述。
//"../../orgC"には追従したいGeometryへのパス。 4@xform = optransform("../../orgC",@Time);
https://www.sidefx.com/ja/docs/houdini/vex/functions/optransform.html
explodematrix
optransformとの合わせ技。
こっちを使うメリットは、Transformノードの移動回転の値として取れることで、50%だけ追従とか、時間ちょっとずらすとかがやりやすい。
後はノード的にTransformノードで使用するので、後から見たときに何か移動回転とかしてるな。というのがわかりやすいのも良い。
Transformノードの、移動回転のXYZに以下を記述。
TranslateX : explodematrix(optransform("../../orgD"), "srt", "xyz", "tx") TranslateY : explodematrix(optransform("../../orgD"), "srt", "xyz", "ty") TranslateZ : explodematrix(optransform("../../orgD"), "srt", "xyz", "tz") RotateX : explodematrix(optransform("../../orgD"), "srt", "xyz", "rx") RotateY : explodematrix(optransform("../../orgD"), "srt", "xyz", "ry") RotateZ : explodematrix(optransform("../../orgD"), "srt", "xyz", "rz")
https://www.sidefx.com/ja/docs/houdini/expressions/explodematrix.html
cracktransform / maketransform
cracktransformはexplodematrixとほぼ同じ。Matrixを分解し、値として取得。
maketransformは再度Matrixに変換する。
cracktranformに以下を記述(Run OverはDetail)
matrix xform = optransform("../../orgE"); vector pivot = {0,0,0}; v@t = cracktransform(XFORM_SRT, XFORM_XYZ, 0, pivot, xform); v@r = cracktransform(XFORM_SRT, XFORM_XYZ, 1, pivot, xform); v@s = cracktransform(XFORM_SRT, XFORM_XYZ, 2, pivot, xform);
↑の後、Transformノードを画像のように設定するとexplodematrixと同じ結果が得られるはず。
maketransformを以下のように記述(Run OverはPoints)
vector trs = detail(0,"t"); vector rot = detail(0,"r"); matrix xform = maketransform(XFORM_SRT, XFORM_XYZ, trs, rot); v@P *= xform;
この結果、どちらも同じ動きになっているはず。
ちなみに、maketransformを以下のように変更し、その後にTransform by Attributesノードを繋いだ結果も同じになる。
vector trs = detail(0,"t"); vector rot = detail(0,"r"); 4@xform = maketransform(XFORM_SRT, XFORM_XYZ, trs, rot);
https://www.sidefx.com/ja/docs/houdini/vex/functions/cracktransform.html
packedfulltransform
AlembicかつDeform(Skining)していないもの限定。Deformしている場合は次!
primintrinsicsにある、packedfulltransform
を使用して移動回転スケールの値を取り出す。
ローモデル等のガイドの置き換えに使える。
Attribute WrangleノードのRun OverをDetailにして以下を記述
vector pivot = {0,0,0}; matrix pft = primintrinsic(0,"packedfulltransform",0); vector t = cracktransform(XFORM_SRT, XFORM_XYZ, 0, pivot, pft); vector r = cracktransform(XFORM_SRT, XFORM_XYZ, 1, pivot, pft); vector s = cracktransform(XFORM_SRT, XFORM_XYZ, 2, pivot, pft); 4@xform = maketransform(XFORM_SRT, XFORM_XYZ, t, r, s);
Transform by AttributesのInvert Transformationにチェックを入れる。
Alembicノードの読込後に移動やスケール、回転をした場合はそれらも追加して計算される。
packedfulltransform応用
Maya等からリグで動いていたキャラをAlembicで書き出したものを特定の位置で止める場合にも使える。
主に原点でシミュレーションかけたりするときに使う。
Deformしたものからはpackedfulltransformが使えないので、コントローラー(カーブかポリゴン)やロケーターを一緒に書き出してそれを利用する。
MayaロケーターをAlembic経由でHoudiniに読み込むには以下のチェックを入れること。
チェックを入れると1ポイントとして読み込まれる。(Mayaと違って形は見えない)
書き出したDeformしていないオブジェクトからpackedfulltransformを取得して動いているものを止めたりすることができる。
blastでロケーターのみを分離し、
Attribute WrangleノードのRun OverをDetailにして以下を記述
スケールの部分を変更しているのは、各DCCでのUnitの違いでHoudiniの1Unit=1mに合わせてスケールかけている部分は戻したくないため。
vector pivot = {0,0,0}; matrix pft = primintrinsic(0,"packedfulltransform",0); vector t = cracktransform(XFORM_SRT, XFORM_XYZ, 0, pivot, pft); vector r = cracktransform(XFORM_SRT, XFORM_XYZ, 1, pivot, pft); vector s = {1,1,1}; 4@xform = maketransform(XFORM_SRT, XFORM_XYZ, t, r, s);
Transform by AttributesのInvert Transformationにチェックを入れる。
この方法、Deformしているやつを1つのPointにPackしてMatch Sizeとか、そのポイントのPをマイナスすればこんなめんどうなことしなくてもいいじゃん。
とか思っていると正確には戻らないので、ひと手間かかるがこちらの方法を取るほうがおすすめ。
transform(intrinsic)
packdfulltransformはMatrix4だけど、transformはMatrix3。Packされてないといけないので注意。
主に後処理でRBDにスケールをかけるのに使った記憶。
wrangleに以下を記述してScaleの値にキーを打つ。
float usrScl = chf("scale"); vector scl = set(usrScl,usrScl,usrScl); matrix3 trans = primintrinsic(0, "transform", @primnum); scale(trans, scl); setprimintrinsic(0, "transform", @primnum, trans);
Nとup
どうしても安定した値を取得できないようなデータになってしまっている場合。
やりたくないし、正確性もかなり低い。
Object MergeのInto This ObjectでSOPにTransform後の状態で読み込む。
デフォームしたりポイント番号が変わったりして取得できないことがないようなポイントを3点選び、以下のようなWrangleを記述。
記述方法は色々あるが、Nとupが変わらないように取得できれば何でも良い。
vector p0 = point(0,"P",0); vector p3 = point(0,"P",3); vector p4 = point(0,"P",4); v@N = p3 - p0; v@up= p4 - p0;
その後Packして1ポイントにし、Copy to Pointsで追従させる。
場合によってはcentroid()もあり。