すあまの備忘録

誰得内容の自分のための非営利目的備忘録ブログ(筆者がわかっても内緒にしてください)

原点に戻したり追従させたり

たびたびアニメーションをずっと原点でしていてほしい場合などがあるので追従させたりする処理のメモ。

シミュレーションやジオメトリ作成を原点でやって実際のポジションへ追従させるとかとか。

他にもいろいろな処理があると思うけど知ってる範囲で。

hipはこちら。Alembicなどは権利的に含んでいません。

obj階層

設定は簡単だが使いづらい。追従しているGeometry内の処理がややこしかったりカメラから見た位置が分かりづらかったり。

やる場合は別のGeometryで何かを作成し、追従させるためのGeometryを用意して中でObject Merge等で読み込むほうが良さそう。

Parent

すごく単純にobj階層でコネクションする。 そうすると親子状態になるので上流の動きを継承するようになる。

f:id:godofsuama:20201228034421p:plain

f:id:godofsuama:20201228034637g:plain

やり方は2つをコネクションするだけ。

他DCC(Maya等)から持ってきたUnitの単位が違うものをobj階層でスケールしてこのように繋いでしまうと下流もスケールかかった状態になってしまうので要注意。

Constraint

Constraint Networkを作成してConstraintする。

f:id:godofsuama:20201228034435p:plain

f:id:godofsuama:20201228034637g:plain

やり方はコンストレインする方のGeometryを以下画像を参考に設定する。

f:id:godofsuama:20201228035342p:plain

A,Bの順で選択し、項目からConstraint Networkを選ぶ。

f:id:godofsuama:20201228035330p:plain

Geometry内にCHOP Networkが作成されるので、その中のノードでConstraintしたいGeometryを選ぶ。

f:id:godofsuama:20201228035509p:plain

Expression / VEXとか

結構色々ある。

こちらのメリットは、参照元の上流でスケール等をかけていたとしてもMatrixとして取り出すことで実際の移動回転値として取り出せること。

optransform

追従したい方のSOPで以下のように組む。Wrangleを見ればわかるが、これのメリットは参照する時間軸をずらすことができること。

遅れたり早かったりということが手軽にできる。

f:id:godofsuama:20201228041354p:plain

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ノードで使用するので、後から見たときに何か移動回転とかしてるな。というのがわかりやすいのも良い。

f:id:godofsuama:20201228042048p:plain

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に変換する。

f:id:godofsuama:20201228045327p:plain

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と同じ結果が得られるはず。

f:id:godofsuama:20201228045519p:plain

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);

f:id:godofsuama:20201228045812p:plain

https://www.sidefx.com/ja/docs/houdini/vex/functions/cracktransform.html

packedfulltransform

AlembicかつDeform(Skining)していないもの限定。Deformしている場合は次!

primintrinsicsにある、packedfulltransformを使用して移動回転スケールの値を取り出す。

ローモデル等のガイドの置き換えに使える。

f:id:godofsuama:20201228163722p:plain

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で書き出したものを特定の位置で止める場合にも使える。

主に原点でシミュレーションかけたりするときに使う。

f:id:godofsuama:20201228165936g:plain
読み込んだAlembic

Deformしたものからはpackedfulltransformが使えないので、コントローラー(カーブかポリゴン)やロケーターを一緒に書き出してそれを利用する。

f:id:godofsuama:20201228165526p:plain

MayaロケーターをAlembic経由でHoudiniに読み込むには以下のチェックを入れること。

チェックを入れると1ポイントとして読み込まれる。(Mayaと違って形は見えない)

f:id:godofsuama:20201228165713p:plain

書き出したDeformしていないオブジェクトからpackedfulltransformを取得して動いているものを止めたりすることができる。

f:id:godofsuama:20201228170007p:plain

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にチェックを入れる。

f:id:godofsuama:20201228170226g:plain
腰で止めた結果

この方法、Deformしているやつを1つのPointにPackしてMatch Sizeとか、そのポイントのPをマイナスすればこんなめんどうなことしなくてもいいじゃん。

とか思っていると正確には戻らないので、ひと手間かかるがこちらの方法を取るほうがおすすめ。

f:id:godofsuama:20201228170628g:plain
Match Sizeなどで戻すと大抵こうなる。

transform(intrinsic)

packdfulltransformはMatrix4だけど、transformはMatrix3。Packされてないといけないので注意。

主に後処理でRBDにスケールをかけるのに使った記憶。

translate

rotate

scale

f:id:godofsuama:20201230185513p:plain

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);

f:id:godofsuama:20201230185935g:plain

Nとup

どうしても安定した値を取得できないようなデータになってしまっている場合。

やりたくないし、正確性もかなり低い。

f:id:godofsuama:20201228042910p:plain

Object MergeのInto This ObjectでSOPにTransform後の状態で読み込む。

f:id:godofsuama:20201228043014p:plain

デフォームしたりポイント番号が変わったりして取得できないことがないようなポイントを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()もあり。