Houdiniの新しいリギングとアニメーション：KineFX機能まとめ

この記事はHoudiniアドベントカレンダー2020　１日目の記事です。

Houdini18.5になりOBJレベルのボーンから、SOPレベルのボーンに移行しました。
これらのツールセットはKineFXと呼ばれ、非常に多くの機能を有します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/d1cf2bd1-5c3f-b1d6-f1f3-b79f30f2c875.png)

そこで今年は、KineFXでよく使うノードのパターン集として、いつでも使えるカンニングペーパー的な記事を目指して執筆します。

#SOP一覧
KineFXの種類は、TabのKineFXで確認できます。
<img width="400px" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/75cb4198-0ce8-6615-bbe7-0a1dac848cb4.png">

SOPには63個の機能があり、それぞれの機能は以下の通りです。
![kinefxsop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/1c597370-8378-4e3b-176d-142dad8d071c.png)

##ジョイントの編集　Rigpose
rigposeノードはKineFXの根幹を担う、最も基本的なノードです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/64d646df-65ca-f0c0-fc66-9b03864b7f43.png)
ポリゴンのライン情報を入力するだけでそれがスケルトンに変換されて、ポイントがジョイントとして動作します。その実態は、Compute Rig Poseノードです。（ノードの中に入るとこのノードが存在します）
RigPoseノードにはname Attributeもtransform Attributeも必須ではありませんが、スケルトンとしての構造が正しい状態でなければなりません。正しい構造とは、「Parentは必ず一つ」そして「ループしていない」構造のことです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/9d1dfc12-0e87-e44d-3e58-4f3eb1a8307f.png)
問題ないスケルトンの変換
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/40400c92-0edd-b5f4-3694-eb7a5d030fb6.png)
変換NG

RigTreeタブ、もしくはRigTreeウィンドウ、RigDoctorでスケルトン構造が正しいかどうかをチェックできます。問題がある場合はエラーを返します。（図ではboxの入力でエラーになっています。エラーの原因はポリゴンが閉じている=ループが発生しているからです）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/22dff298-e274-e9cd-49aa-d05e43a4ec40.png)

###parentは何で定義されているのか
Attributeではなく、頂点(vertex)の順で決定します。つまり、ポイント番号をsortのreverseを逆にしてもボーンの方向は変わりません。逆転させたい場合はreverseノードを使用します。線形頂点番号の逆転が発生するため、親子関係が逆転します。ただし、Parent１つに対してChildが複数存在する場合はトラバースしたものとして別途処理されます。これを逆転させるとParentが複数となるのでエラーとなります。

##スケルトンの健全性確認　RigDoctor
スケルトンの健全性を確認してくれます。Debug Hierarchyにチェックをしておくと、不正なスケルトンの場合に検知してくれます。（！マークで警告してくれます。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/addf73ae-2d83-c8a2-c9e8-fdf9593e4a75.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/f7d9b309-206a-4271-28bf-da6f4a43d385.png)
ただし、最も使用する用途としては、name Attributeそしてtransform Attributeの付与です。
デフォルトでPoint Namesの設定として接頭辞の設定が可能です。（名前だけ付与する場合はDegug Hierarchyなどは不要な処理なのでチェックを外してもよいかもしれません）
transform Attributeの付与はデフォルトではチェックされていません。付与したい場合は、Initialize Transformsにチェックを入れます。するとlocaltransform Attributeとtransform Attributeが付与されます。

##スケルトンの作成と編集　Skeleton　
１からスケルトンを作成することができます。また、正しい構造であればポリゴンを入力することでスケルトンへの変換も可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/20bd9038-2e94-9856-c619-4fdf99e5e3a5.png)
スケルトンの作成時は、ビューポート上部のエリアをまずは設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/59200231-ce28-6d17-c2e4-2af4a131a6c8.png)
###スケルトンの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/f8d659c4-233e-e3c3-e35a-fdf9bacfaccd.png)
ジョイント作成時のnameのデフォルトではpoint_*です。名前を変えたい場合は、後からジョイントを選択して変更する必要があります。ジョイントの作成後に位置の微調整を行いたい場合は、Mode:CreateからMode:Modifyに変更して、リグで右クリックからの　ShowHandleのチェックを入れてハンドルを表示さて操作します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/1b1d13d0-63a3-7f0f-ff63-202e2e131e5a.png)

いちいちジョイントを選択して名前変更するのが面倒な場合は、Skeletonノード選択状態で、RigTreeでそれぞれの名前をダブルクリックすると名前を編集できます。※ジョイントのNameは必ず固有でなければならないため、同じ名前は厳禁です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/c4602ac9-6176-342e-dc37-4f0ce44ad4fb.png)

同様にskeleton選択時であればビューポートのジョイント選択時、「P」の押下でパラメータを出して名前やジョイントの位置変更が可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/5f778253-1bd5-1b33-ec9f-eab7ccbcd803.png)


###stashに注意
skeletonより上流を変更したのにデータが反映されない場合はstash（しまっておく）機能が働いている可能性があります。上流のデータの再取得のためにはstash inputを行う必要があります。ただし、ここで様々な作業を行っていた場合そのデータも消えてしまうので、skeletonの利用は計画的に行う必要があります。

###キャプチャとデフォーム
Houdiniには従来からのキャプチャ方法が3種類ありますが、KineFXでは基本的にBoneCaptureBiharmonicを使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/9dca1ac1-8a65-b5e1-5434-49610919309f.png)
rigposeを回転すると、ジオメトリがキャプチャされて動作します。
![capp.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/40ee8859-78cd-675c-c363-b842d1dd3855.gif)
objレベルの存在しないボーンを探しにいってしまうWarningは出ますが、BoneCaptureProximityでも一応動作します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/36fb78b4-9de1-803a-19cf-5d5d53cb820e.png)
最後の一つBoneCaptureは動作しません。

従来の３つのキャプチャに加え、KineFXではPackされたオブジェクトのキャプチャが追加されています。
それがCapturePackedGeometryです。機械のように固いオブジェクトをジョイントに対して追従させます。
最終的な変形はBoneDeformで行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/6db4cec3-ac74-f254-5204-5ec24e14e576.png)
![bcap.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/5e418198-7bad-bcab-c1d0-d02e5737233b.gif)


##IK Chains
IKChainsの注意点は、Blendの初期値が0であること
その他に、複数のIKを設定する場合、RootがGoalの先に存在する場合、Goalが固定されて動作するという事です。仮に、IKchainsを連ねる場合はタブではなく、別ノードとしてIKChainsを付与してやる必要があります。
![ikchain.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/266101d6-a258-76ef-c2f9-be92f848266e.gif)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/67eff362-7e88-1579-d2f5-1f68cc1d536b.png)
twistとgoalが用意できない場合は、Match By Nameにチェックを入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/61ce8e03-c9e9-5fb1-16b2-754c6a268735.png)

##Full Body IK
フルボディ インバース キネマティクス アルゴリズムを使用して、モーションを SOP ベースのスケルトンに転送します。このノードは、name Attribute、transform Attributeが必須です。
主にリターゲティング時はmappointsと併用し、MapUsingではMapping Attributeを使用します。
name Attributeのみで動作させる場合は、Match By Attributeに変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/c3439676-d0ae-b6d2-3c54-12b4f5032320.png)

###少ないコントローラーでの操作
name Attributeさえあれば、基本的にMatch By Attributeを行うと、mappointなしで動作させることができます。最終的な形にRigを移動した後、SkeletonBlendやBlendShapeを行うことで、スムーズなアニメーションを行うことも可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/49d733df-f73d-411e-a826-7ca5c7abdb94.png)
![tree.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/3d8ae9cd-3cc1-8431-c4f0-528abcc60c24.gif)

###リターゲット
リターゲティングについては、既に様々なサイトで解説されているので、そちらを参照ください。
[SideFX　KINEFX MOTION RETARGETING (モーションリターゲティング)](https://www.sidefx.com/ja/tutorials/houdini-185-quickstart-kinefx-motion-retargeting/)
[ボーンデジタル　KineFXでモーションリターゲティング](https://support.borndigital.co.jp/hc/ja/articles/900003192043-KineFX%E3%81%A7%E3%83%A2%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%AA%E3%82%BF%E3%83%BC%E3%82%B2%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0)
[IndyZone　KineFX](https://houdinifx.jp/blog/houdini18-5-kine-fx/)

メモ：RigMatchPoseをする前に、第2インプットにrestposeを入れ込んだRigStashPoseを埋め込んでおくと、微調整が減って便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/d035a28f-b15e-481f-1e79-e9706e7afba3.png)


###回転角度制限　FBIK Configure Joints
FullBodyIKキネマティクス ソルバーで使用されるジョイントプロパティを設定するノードですが、便利な機能が存在しています。FullBodyIKで回転する際の角度制限を付けることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/3fa8d717-ffb6-fae1-6345-35274c04f084.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/d1bad6cb-c3be-0df3-1111-75b7ebfbf77c.png)

FullBodyIK時の回転角度の制御は、ConfigurationsのLimitにおいて行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/57e89d7a-cfe3-9614-2799-47cc23ba4a41.png)
すると、辞書型のfbik_jointconfig Attributeが付与されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/03b61637-a695-0364-5ec0-f0f53116e710.png)

###重心取得　FBIK Configure Joints
全体の重心を計算して、1つのポイントを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/780393e6-b2c7-fcf9-27cf-91204cac9bc1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/3f1850aa-72da-3be7-9234-3b821a4c8a46.png)
重心はCenter Of Mass のAdd Point at Center of Massにチェックを入れることで設定できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/0636add2-ca00-b44a-0863-25d4666f0119.png)
このように単体での重心取得に使用する以外に、FullBodyIKノード内の、Add Center of Mass Targetのチェックと合わせて使用すると、バランスを取るような動作を実現できます。

##ジョイントの選択　Attach Control Geometry
AttachControlGeometryを使用して、ジョイントに対して、必要なオブジェクトを付与すると便利です。
注意点としてこのオブジェクトに付与するnameはprimitiveタイプであるという点です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/085bd5ad-ce1d-c8be-5d0f-923e6df69dc5.png)
sphereのジオメトリをアタッチした場合、sphereのクリックがjointの選択と同義となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/0af774b2-7fc5-c19e-e6e7-b77ceb5c39dc.png)


#VOP一覧
RigAttributeVOPにもKineFXノードが追加されています。
<img width="400px" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/04b635b1-3c21-0f35-0475-9fa459b643cb.png">

VOPには38個の機能があり、それぞれの機能は以下の通りです。
![KINEFXVOP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/c6f6a9b8-4cfe-fec5-f72f-178d3c73d9db.png)


##特定方向を見る LookAt
LookAt(KineFX)とLookAtConstraintの違いは、Offset機能とBlend機能の有り無しです。つまり、LookAtConstraintはLookAt(KineFX)のラッパーです。
オフセットの更新ボタンを押すと、現在の入力を使用した計算の結果が隠され、これが「rest」変換として設定されます。
LookAtの注意点は、LookAtのxformに入力するのは、ボーンの先端ではなく、実際に回転を行う根本だということです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/157c30a8-c1d5-0bcf-780b-a53aab7cd9f0.png)
LookAtのtoについてはターゲットとなるpoint_3を、fromは実際に位置情報が変更するpoint_2ではなく回転が発生するpoint_1を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/909c0ae3-1137-ed0e-f134-55e135990728.png)

![bonelookat.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/d4d48229-08c3-cf0d-e622-bf44071ab2a6.gif)

##親に追従する Parent Constraint
parent constraintではupdate offset、clear offsetの設定によっては、思わぬ状態でconstraintされるので注意が必要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/8cc453f6-a706-8cb9-03e4-58da5c47912a.png)
new parentに付与することで、実際にスケルトンの結合が行われなくとも、親の動きに追従します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/4f393d3e-290b-5c64-2b83-bdccb71250b5.png)

![const.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/70f669a5-99bf-9db8-51b2-a10769e489c2.gif)

##カーブを追従させる Curve Solver
おおまかなガイド用のラインを作成し、そのガイドにそってカーブを作成します。髪の毛やしっぽなどに応用できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/52a3dda8-0572-37c8-3f7a-756297dfb764.png)
これまではgetpointtransformで取得していたが、getpointtransform「s」で複数のポイントをワイルドカード「*」で一括取得する、そしてsettransfomsで適用する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/ed4870a6-c03f-8b67-b65a-618176f347c1.png)
![csolver.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/3ec38f92-bbcb-6b46-5621-435547c612b4.gif)

##パスに追従させる Transform From Path
パスにそって、移動するアニメーションを作る場合にこのノードを使用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/adce2bb8-f755-7385-79f0-0113af38d637.png)
curveposに対して0→1のアニメーションを行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/686edda9-9c89-eb3c-c0fa-19ac5d7edbf0.png)
デフォルトだと、LookAtOffsetが0なので、カーブの向きが固定されてしまいます。
カーブの方向に向いてほしい場合は、この値を少し上げます。
![cvv.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/bc0e96a3-3cf3-ea36-5dc6-c10f55147ed9.gif)

#まとめ
今回は使いそうなノードを抜粋して記述しました。
これ以外にもRigAttributeWrangleやMotionClipなど色々な機能がありますが、時間がいくらあっても足りないので、今回はこれでおわりにしたいと思います。
去年書いた、「[ディニ子をつくる：Houdiniでキャラクターモデリング](https://qiita.com/jyouryuusui/items/ad15495a702ee957dbe8)」と「[HoudiniでUV展開＆リグ入門](https://qiita.com/jyouryuusui/items/e15d53e88e9cc018d18f)」でオブジェクトレベルのボーンを嫌というほど触った身からすると、KineFXは本当に使いやすいので助かります。
※ディニ子もOBJボーンからKineFXに生まれ変わりました。去年のモデルと見比べてみても面白いかもしれません。
![diniani.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151589/89ac3680-fc97-7460-bac9-ca1d44854c46.gif)
Houdini19ではさらにリギングやアニメーションが拡張されるとのことです。
キャラクターアニメーション以外にも、HoudiniのプロシージャルワークフローにKineFXは想像しないような活用がされていくでしょう。
この記事が今後のKineFX利用時のお役に立てれば幸いです。